Blame view

drivers/md/dm-linear.c 3.82 KB
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1
2
3
4
5
6
7
  /*
   * Copyright (C) 2001-2003 Sistina Software (UK) Limited.
   *
   * This file is released under the GPL.
   */
  
  #include "dm.h"
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
8
9
10
11
12
  #include <linux/module.h>
  #include <linux/init.h>
  #include <linux/blkdev.h>
  #include <linux/bio.h>
  #include <linux/slab.h>
586e80e6e   Mikulas Patocka   dm: remove dm hea...
13
  #include <linux/device-mapper.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
14

72d948616   Alasdair G Kergon   [PATCH] dm: impro...
15
  #define DM_MSG_PREFIX "linear"
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
16
17
18
19
20
21
22
23
24
25
26
27
28
29
  /*
   * Linear: maps a linear range of a device.
   */
  struct linear_c {
  	struct dm_dev *dev;
  	sector_t start;
  };
  
  /*
   * Construct a linear mapping: <dev_path> <offset>
   */
  static int linear_ctr(struct dm_target *ti, unsigned int argc, char **argv)
  {
  	struct linear_c *lc;
4ee218cd6   Andrew Morton   [PATCH] dm: remov...
30
  	unsigned long long tmp;
31998ef19   Mikulas Patocka   dm: reject traili...
31
  	char dummy;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
32
33
  
  	if (argc != 2) {
72d948616   Alasdair G Kergon   [PATCH] dm: impro...
34
  		ti->error = "Invalid argument count";
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
35
36
37
38
39
40
41
42
  		return -EINVAL;
  	}
  
  	lc = kmalloc(sizeof(*lc), GFP_KERNEL);
  	if (lc == NULL) {
  		ti->error = "dm-linear: Cannot allocate linear context";
  		return -ENOMEM;
  	}
31998ef19   Mikulas Patocka   dm: reject traili...
43
  	if (sscanf(argv[1], "%llu%c", &tmp, &dummy) != 1) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
44
45
46
  		ti->error = "dm-linear: Invalid device sector";
  		goto bad;
  	}
4ee218cd6   Andrew Morton   [PATCH] dm: remov...
47
  	lc->start = tmp;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
48

8215d6ec5   Nikanth Karthikesan   dm table: remove ...
49
  	if (dm_get_device(ti, argv[0], dm_table_get_mode(ti->table), &lc->dev)) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
50
51
52
  		ti->error = "dm-linear: Device lookup failed";
  		goto bad;
  	}
55a62eef8   Alasdair G Kergon   dm: rename reques...
53
54
55
  	ti->num_flush_bios = 1;
  	ti->num_discard_bios = 1;
  	ti->num_write_same_bios = 1;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
  	ti->private = lc;
  	return 0;
  
        bad:
  	kfree(lc);
  	return -EINVAL;
  }
  
  static void linear_dtr(struct dm_target *ti)
  {
  	struct linear_c *lc = (struct linear_c *) ti->private;
  
  	dm_put_device(ti, lc->dev);
  	kfree(lc);
  }
7bc3447b6   Milan Broz   dm: linear add merge
71
  static sector_t linear_map_sector(struct dm_target *ti, sector_t bi_sector)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
72
  {
7bc3447b6   Milan Broz   dm: linear add merge
73
  	struct linear_c *lc = ti->private;
b441a262e   Alasdair G Kergon   dm: use dm_target...
74
  	return lc->start + dm_target_offset(ti, bi_sector);
7bc3447b6   Milan Broz   dm: linear add merge
75
76
77
78
79
  }
  
  static void linear_map_bio(struct dm_target *ti, struct bio *bio)
  {
  	struct linear_c *lc = ti->private;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
80
81
  
  	bio->bi_bdev = lc->dev->bdev;
433bcac56   Mikulas Patocka   dm: linear suppor...
82
  	if (bio_sectors(bio))
4f024f379   Kent Overstreet   block: Abstract o...
83
84
  		bio->bi_iter.bi_sector =
  			linear_map_sector(ti, bio->bi_iter.bi_sector);
7bc3447b6   Milan Broz   dm: linear add merge
85
  }
7de3ee57d   Mikulas Patocka   dm: remove map_info
86
  static int linear_map(struct dm_target *ti, struct bio *bio)
7bc3447b6   Milan Broz   dm: linear add merge
87
88
  {
  	linear_map_bio(ti, bio);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
89

d2a7ad29a   Kiyoshi Ueda   [PATCH] dm: map a...
90
  	return DM_MAPIO_REMAPPED;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
91
  }
fd7c092e7   Mikulas Patocka   dm: fix truncated...
92
93
  static void linear_status(struct dm_target *ti, status_type_t type,
  			  unsigned status_flags, char *result, unsigned maxlen)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
94
95
96
97
98
99
100
101
102
  {
  	struct linear_c *lc = (struct linear_c *) ti->private;
  
  	switch (type) {
  	case STATUSTYPE_INFO:
  		result[0] = '\0';
  		break;
  
  	case STATUSTYPE_TABLE:
4ee218cd6   Andrew Morton   [PATCH] dm: remov...
103
104
  		snprintf(result, maxlen, "%s %llu", lc->dev->name,
  				(unsigned long long)lc->start);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
105
106
  		break;
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
107
  }
647b3d008   Al Viro   [PATCH] lose unus...
108
  static int linear_ioctl(struct dm_target *ti, unsigned int cmd,
ab17ffa44   Milan Broz   [PATCH] dm linear...
109
110
111
  			unsigned long arg)
  {
  	struct linear_c *lc = (struct linear_c *) ti->private;
ec8013bed   Paolo Bonzini   dm: do not forwar...
112
113
114
115
116
117
118
119
120
121
122
  	struct dm_dev *dev = lc->dev;
  	int r = 0;
  
  	/*
  	 * Only pass ioctls through if the device sizes match exactly.
  	 */
  	if (lc->start ||
  	    ti->len != i_size_read(dev->bdev->bd_inode) >> SECTOR_SHIFT)
  		r = scsi_verify_blk_ioctl(NULL, cmd);
  
  	return r ? : __blkdev_driver_ioctl(dev->bdev, dev->mode, cmd, arg);
ab17ffa44   Milan Broz   [PATCH] dm linear...
123
  }
7bc3447b6   Milan Broz   dm: linear add merge
124
125
126
127
128
129
130
131
132
133
134
135
136
137
  static int linear_merge(struct dm_target *ti, struct bvec_merge_data *bvm,
  			struct bio_vec *biovec, int max_size)
  {
  	struct linear_c *lc = ti->private;
  	struct request_queue *q = bdev_get_queue(lc->dev->bdev);
  
  	if (!q->merge_bvec_fn)
  		return max_size;
  
  	bvm->bi_bdev = lc->dev->bdev;
  	bvm->bi_sector = linear_map_sector(ti, bvm->bi_sector);
  
  	return min(max_size, q->merge_bvec_fn(q, bvm, biovec));
  }
af4874e03   Mike Snitzer   dm target:s intro...
138
139
140
141
  static int linear_iterate_devices(struct dm_target *ti,
  				  iterate_devices_callout_fn fn, void *data)
  {
  	struct linear_c *lc = ti->private;
5dea271b6   Mike Snitzer   dm table: pass co...
142
  	return fn(ti, lc->dev, lc->start, ti->len, data);
af4874e03   Mike Snitzer   dm target:s intro...
143
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
144
145
  static struct target_type linear_target = {
  	.name   = "linear",
fd7c092e7   Mikulas Patocka   dm: fix truncated...
146
  	.version = {1, 2, 1},
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
147
148
149
150
151
  	.module = THIS_MODULE,
  	.ctr    = linear_ctr,
  	.dtr    = linear_dtr,
  	.map    = linear_map,
  	.status = linear_status,
ab17ffa44   Milan Broz   [PATCH] dm linear...
152
  	.ioctl  = linear_ioctl,
7bc3447b6   Milan Broz   dm: linear add merge
153
  	.merge  = linear_merge,
af4874e03   Mike Snitzer   dm target:s intro...
154
  	.iterate_devices = linear_iterate_devices,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
155
156
157
158
159
160
161
  };
  
  int __init dm_linear_init(void)
  {
  	int r = dm_register_target(&linear_target);
  
  	if (r < 0)
72d948616   Alasdair G Kergon   [PATCH] dm: impro...
162
  		DMERR("register failed %d", r);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
163
164
165
166
167
168
  
  	return r;
  }
  
  void dm_linear_exit(void)
  {
10d3bd09a   Mikulas Patocka   dm: consolidate t...
169
  	dm_unregister_target(&linear_target);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
170
  }