Blame view

drivers/md/dm-linear.c 3.79 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;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
31
32
  
  	if (argc != 2) {
72d948616   Alasdair G Kergon   [PATCH] dm: impro...
33
  		ti->error = "Invalid argument count";
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
34
35
36
37
38
39
40
41
  		return -EINVAL;
  	}
  
  	lc = kmalloc(sizeof(*lc), GFP_KERNEL);
  	if (lc == NULL) {
  		ti->error = "dm-linear: Cannot allocate linear context";
  		return -ENOMEM;
  	}
4ee218cd6   Andrew Morton   [PATCH] dm: remov...
42
  	if (sscanf(argv[1], "%llu", &tmp) != 1) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
43
44
45
  		ti->error = "dm-linear: Invalid device sector";
  		goto bad;
  	}
4ee218cd6   Andrew Morton   [PATCH] dm: remov...
46
  	lc->start = tmp;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
47

8215d6ec5   Nikanth Karthikesan   dm table: remove ...
48
  	if (dm_get_device(ti, argv[0], dm_table_get_mode(ti->table), &lc->dev)) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
49
50
51
  		ti->error = "dm-linear: Device lookup failed";
  		goto bad;
  	}
433bcac56   Mikulas Patocka   dm: linear suppor...
52
  	ti->num_flush_requests = 1;
5ae89a872   Mike Snitzer   dm: linear suppor...
53
  	ti->num_discard_requests = 1;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
  	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
69
  static sector_t linear_map_sector(struct dm_target *ti, sector_t bi_sector)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
70
  {
7bc3447b6   Milan Broz   dm: linear add merge
71
  	struct linear_c *lc = ti->private;
b441a262e   Alasdair G Kergon   dm: use dm_target...
72
  	return lc->start + dm_target_offset(ti, bi_sector);
7bc3447b6   Milan Broz   dm: linear add merge
73
74
75
76
77
  }
  
  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
78
79
  
  	bio->bi_bdev = lc->dev->bdev;
433bcac56   Mikulas Patocka   dm: linear suppor...
80
81
  	if (bio_sectors(bio))
  		bio->bi_sector = linear_map_sector(ti, bio->bi_sector);
7bc3447b6   Milan Broz   dm: linear add merge
82
83
84
85
86
87
  }
  
  static int linear_map(struct dm_target *ti, struct bio *bio,
  		      union map_info *map_context)
  {
  	linear_map_bio(ti, bio);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
88

d2a7ad29a   Kiyoshi Ueda   [PATCH] dm: map a...
89
  	return DM_MAPIO_REMAPPED;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
90
91
92
93
94
95
96
97
98
99
100
101
102
  }
  
  static int linear_status(struct dm_target *ti, status_type_t type,
  			 char *result, unsigned int maxlen)
  {
  	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
107
108
  		break;
  	}
  	return 0;
  }
647b3d008   Al Viro   [PATCH] lose unus...
109
  static int linear_ioctl(struct dm_target *ti, unsigned int cmd,
ab17ffa44   Milan Broz   [PATCH] dm linear...
110
111
112
  			unsigned long arg)
  {
  	struct linear_c *lc = (struct linear_c *) ti->private;
ec8013bed   Paolo Bonzini   dm: do not forwar...
113
114
115
116
117
118
119
120
121
122
123
  	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...
124
  }
7bc3447b6   Milan Broz   dm: linear add merge
125
126
127
128
129
130
131
132
133
134
135
136
137
138
  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...
139
140
141
142
  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...
143
  	return fn(ti, lc->dev, lc->start, ti->len, data);
af4874e03   Mike Snitzer   dm target:s intro...
144
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
145
146
  static struct target_type linear_target = {
  	.name   = "linear",
af4874e03   Mike Snitzer   dm target:s intro...
147
  	.version = {1, 1, 0},
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
148
149
150
151
152
  	.module = THIS_MODULE,
  	.ctr    = linear_ctr,
  	.dtr    = linear_dtr,
  	.map    = linear_map,
  	.status = linear_status,
ab17ffa44   Milan Broz   [PATCH] dm linear...
153
  	.ioctl  = linear_ioctl,
7bc3447b6   Milan Broz   dm: linear add merge
154
  	.merge  = linear_merge,
af4874e03   Mike Snitzer   dm target:s intro...
155
  	.iterate_devices = linear_iterate_devices,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
156
157
158
159
160
161
162
  };
  
  int __init dm_linear_init(void)
  {
  	int r = dm_register_target(&linear_target);
  
  	if (r < 0)
72d948616   Alasdair G Kergon   [PATCH] dm: impro...
163
  		DMERR("register failed %d", r);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
164
165
166
167
168
169
  
  	return r;
  }
  
  void dm_linear_exit(void)
  {
10d3bd09a   Mikulas Patocka   dm: consolidate t...
170
  	dm_unregister_target(&linear_target);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
171
  }