diff options
Diffstat (limited to 'drivers/md/dm-snap.c')
| -rw-r--r-- | drivers/md/dm-snap.c | 53 |
1 files changed, 35 insertions, 18 deletions
diff --git a/drivers/md/dm-snap.c b/drivers/md/dm-snap.c index ebddef5237e4..220a06bfe91b 100644 --- a/drivers/md/dm-snap.c +++ b/drivers/md/dm-snap.c | |||
| @@ -2141,6 +2141,10 @@ static int origin_write_extent(struct dm_snapshot *merging_snap, | |||
| 2141 | * Origin: maps a linear range of a device, with hooks for snapshotting. | 2141 | * Origin: maps a linear range of a device, with hooks for snapshotting. |
| 2142 | */ | 2142 | */ |
| 2143 | 2143 | ||
| 2144 | struct dm_origin { | ||
| 2145 | struct dm_dev *dev; | ||
| 2146 | }; | ||
| 2147 | |||
| 2144 | /* | 2148 | /* |
| 2145 | * Construct an origin mapping: <dev_path> | 2149 | * Construct an origin mapping: <dev_path> |
| 2146 | * The context for an origin is merely a 'struct dm_dev *' | 2150 | * The context for an origin is merely a 'struct dm_dev *' |
| @@ -2149,41 +2153,54 @@ static int origin_write_extent(struct dm_snapshot *merging_snap, | |||
| 2149 | static int origin_ctr(struct dm_target *ti, unsigned int argc, char **argv) | 2153 | static int origin_ctr(struct dm_target *ti, unsigned int argc, char **argv) |
| 2150 | { | 2154 | { |
| 2151 | int r; | 2155 | int r; |
| 2152 | struct dm_dev *dev; | 2156 | struct dm_origin *o; |
| 2153 | 2157 | ||
| 2154 | if (argc != 1) { | 2158 | if (argc != 1) { |
| 2155 | ti->error = "origin: incorrect number of arguments"; | 2159 | ti->error = "origin: incorrect number of arguments"; |
| 2156 | return -EINVAL; | 2160 | return -EINVAL; |
| 2157 | } | 2161 | } |
| 2158 | 2162 | ||
| 2159 | r = dm_get_device(ti, argv[0], dm_table_get_mode(ti->table), &dev); | 2163 | o = kmalloc(sizeof(struct dm_origin), GFP_KERNEL); |
| 2164 | if (!o) { | ||
| 2165 | ti->error = "Cannot allocate private origin structure"; | ||
| 2166 | r = -ENOMEM; | ||
| 2167 | goto bad_alloc; | ||
| 2168 | } | ||
| 2169 | |||
| 2170 | r = dm_get_device(ti, argv[0], dm_table_get_mode(ti->table), &o->dev); | ||
| 2160 | if (r) { | 2171 | if (r) { |
| 2161 | ti->error = "Cannot get target device"; | 2172 | ti->error = "Cannot get target device"; |
| 2162 | return r; | 2173 | goto bad_open; |
| 2163 | } | 2174 | } |
| 2164 | 2175 | ||
| 2165 | ti->private = dev; | 2176 | ti->private = o; |
| 2166 | ti->num_flush_bios = 1; | 2177 | ti->num_flush_bios = 1; |
| 2167 | 2178 | ||
| 2168 | return 0; | 2179 | return 0; |
| 2180 | |||
| 2181 | bad_open: | ||
| 2182 | kfree(o); | ||
| 2183 | bad_alloc: | ||
| 2184 | return r; | ||
| 2169 | } | 2185 | } |
| 2170 | 2186 | ||
| 2171 | static void origin_dtr(struct dm_target *ti) | 2187 | static void origin_dtr(struct dm_target *ti) |
| 2172 | { | 2188 | { |
| 2173 | struct dm_dev *dev = ti->private; | 2189 | struct dm_origin *o = ti->private; |
| 2174 | dm_put_device(ti, dev); | 2190 | dm_put_device(ti, o->dev); |
| 2191 | kfree(o); | ||
| 2175 | } | 2192 | } |
| 2176 | 2193 | ||
| 2177 | static int origin_map(struct dm_target *ti, struct bio *bio) | 2194 | static int origin_map(struct dm_target *ti, struct bio *bio) |
| 2178 | { | 2195 | { |
| 2179 | struct dm_dev *dev = ti->private; | 2196 | struct dm_origin *o = ti->private; |
| 2180 | bio->bi_bdev = dev->bdev; | 2197 | bio->bi_bdev = o->dev->bdev; |
| 2181 | 2198 | ||
| 2182 | if (bio->bi_rw & REQ_FLUSH) | 2199 | if (bio->bi_rw & REQ_FLUSH) |
| 2183 | return DM_MAPIO_REMAPPED; | 2200 | return DM_MAPIO_REMAPPED; |
| 2184 | 2201 | ||
| 2185 | /* Only tell snapshots if this is a write */ | 2202 | /* Only tell snapshots if this is a write */ |
| 2186 | return (bio_rw(bio) == WRITE) ? do_origin(dev, bio) : DM_MAPIO_REMAPPED; | 2203 | return (bio_rw(bio) == WRITE) ? do_origin(o->dev, bio) : DM_MAPIO_REMAPPED; |
| 2187 | } | 2204 | } |
| 2188 | 2205 | ||
| 2189 | /* | 2206 | /* |
| @@ -2192,15 +2209,15 @@ static int origin_map(struct dm_target *ti, struct bio *bio) | |||
| 2192 | */ | 2209 | */ |
| 2193 | static void origin_resume(struct dm_target *ti) | 2210 | static void origin_resume(struct dm_target *ti) |
| 2194 | { | 2211 | { |
| 2195 | struct dm_dev *dev = ti->private; | 2212 | struct dm_origin *o = ti->private; |
| 2196 | 2213 | ||
| 2197 | ti->max_io_len = get_origin_minimum_chunksize(dev->bdev); | 2214 | ti->max_io_len = get_origin_minimum_chunksize(o->dev->bdev); |
| 2198 | } | 2215 | } |
| 2199 | 2216 | ||
| 2200 | static void origin_status(struct dm_target *ti, status_type_t type, | 2217 | static void origin_status(struct dm_target *ti, status_type_t type, |
| 2201 | unsigned status_flags, char *result, unsigned maxlen) | 2218 | unsigned status_flags, char *result, unsigned maxlen) |
| 2202 | { | 2219 | { |
| 2203 | struct dm_dev *dev = ti->private; | 2220 | struct dm_origin *o = ti->private; |
| 2204 | 2221 | ||
| 2205 | switch (type) { | 2222 | switch (type) { |
| 2206 | case STATUSTYPE_INFO: | 2223 | case STATUSTYPE_INFO: |
| @@ -2208,7 +2225,7 @@ static void origin_status(struct dm_target *ti, status_type_t type, | |||
| 2208 | break; | 2225 | break; |
| 2209 | 2226 | ||
| 2210 | case STATUSTYPE_TABLE: | 2227 | case STATUSTYPE_TABLE: |
| 2211 | snprintf(result, maxlen, "%s", dev->name); | 2228 | snprintf(result, maxlen, "%s", o->dev->name); |
| 2212 | break; | 2229 | break; |
| 2213 | } | 2230 | } |
| 2214 | } | 2231 | } |
| @@ -2216,13 +2233,13 @@ static void origin_status(struct dm_target *ti, status_type_t type, | |||
| 2216 | static int origin_merge(struct dm_target *ti, struct bvec_merge_data *bvm, | 2233 | static int origin_merge(struct dm_target *ti, struct bvec_merge_data *bvm, |
| 2217 | struct bio_vec *biovec, int max_size) | 2234 | struct bio_vec *biovec, int max_size) |
| 2218 | { | 2235 | { |
| 2219 | struct dm_dev *dev = ti->private; | 2236 | struct dm_origin *o = ti->private; |
| 2220 | struct request_queue *q = bdev_get_queue(dev->bdev); | 2237 | struct request_queue *q = bdev_get_queue(o->dev->bdev); |
| 2221 | 2238 | ||
| 2222 | if (!q->merge_bvec_fn) | 2239 | if (!q->merge_bvec_fn) |
| 2223 | return max_size; | 2240 | return max_size; |
| 2224 | 2241 | ||
| 2225 | bvm->bi_bdev = dev->bdev; | 2242 | bvm->bi_bdev = o->dev->bdev; |
| 2226 | 2243 | ||
| 2227 | return min(max_size, q->merge_bvec_fn(q, bvm, biovec)); | 2244 | return min(max_size, q->merge_bvec_fn(q, bvm, biovec)); |
| 2228 | } | 2245 | } |
| @@ -2230,9 +2247,9 @@ static int origin_merge(struct dm_target *ti, struct bvec_merge_data *bvm, | |||
| 2230 | static int origin_iterate_devices(struct dm_target *ti, | 2247 | static int origin_iterate_devices(struct dm_target *ti, |
| 2231 | iterate_devices_callout_fn fn, void *data) | 2248 | iterate_devices_callout_fn fn, void *data) |
| 2232 | { | 2249 | { |
| 2233 | struct dm_dev *dev = ti->private; | 2250 | struct dm_origin *o = ti->private; |
| 2234 | 2251 | ||
| 2235 | return fn(ti, dev, 0, ti->len, data); | 2252 | return fn(ti, o->dev, 0, ti->len, data); |
| 2236 | } | 2253 | } |
| 2237 | 2254 | ||
| 2238 | static struct target_type origin_target = { | 2255 | static struct target_type origin_target = { |
