diff options
Diffstat (limited to 'drivers/md/dm-snap.c')
-rw-r--r-- | drivers/md/dm-snap.c | 82 |
1 files changed, 11 insertions, 71 deletions
diff --git a/drivers/md/dm-snap.c b/drivers/md/dm-snap.c index 5974d3094d97..9ecff5f3023a 100644 --- a/drivers/md/dm-snap.c +++ b/drivers/md/dm-snap.c | |||
@@ -19,7 +19,6 @@ | |||
19 | #include <linux/vmalloc.h> | 19 | #include <linux/vmalloc.h> |
20 | #include <linux/log2.h> | 20 | #include <linux/log2.h> |
21 | #include <linux/dm-kcopyd.h> | 21 | #include <linux/dm-kcopyd.h> |
22 | #include <linux/workqueue.h> | ||
23 | 22 | ||
24 | #include "dm-exception-store.h" | 23 | #include "dm-exception-store.h" |
25 | 24 | ||
@@ -41,11 +40,6 @@ static const char dm_snapshot_merge_target_name[] = "snapshot-merge"; | |||
41 | #define SNAPSHOT_COPY_PRIORITY 2 | 40 | #define SNAPSHOT_COPY_PRIORITY 2 |
42 | 41 | ||
43 | /* | 42 | /* |
44 | * Reserve 1MB for each snapshot initially (with minimum of 1 page). | ||
45 | */ | ||
46 | #define SNAPSHOT_PAGES (((1UL << 20) >> PAGE_SHIFT) ? : 1) | ||
47 | |||
48 | /* | ||
49 | * The size of the mempool used to track chunks in use. | 43 | * The size of the mempool used to track chunks in use. |
50 | */ | 44 | */ |
51 | #define MIN_IOS 256 | 45 | #define MIN_IOS 256 |
@@ -80,9 +74,6 @@ struct dm_snapshot { | |||
80 | /* Origin writes don't trigger exceptions until this is set */ | 74 | /* Origin writes don't trigger exceptions until this is set */ |
81 | int active; | 75 | int active; |
82 | 76 | ||
83 | /* Whether or not owning mapped_device is suspended */ | ||
84 | int suspended; | ||
85 | |||
86 | atomic_t pending_exceptions_count; | 77 | atomic_t pending_exceptions_count; |
87 | 78 | ||
88 | mempool_t *pending_pool; | 79 | mempool_t *pending_pool; |
@@ -106,10 +97,6 @@ struct dm_snapshot { | |||
106 | 97 | ||
107 | struct dm_kcopyd_client *kcopyd_client; | 98 | struct dm_kcopyd_client *kcopyd_client; |
108 | 99 | ||
109 | /* Queue of snapshot writes for ksnapd to flush */ | ||
110 | struct bio_list queued_bios; | ||
111 | struct work_struct queued_bios_work; | ||
112 | |||
113 | /* Wait for events based on state_bits */ | 100 | /* Wait for events based on state_bits */ |
114 | unsigned long state_bits; | 101 | unsigned long state_bits; |
115 | 102 | ||
@@ -160,9 +147,6 @@ struct dm_dev *dm_snap_cow(struct dm_snapshot *s) | |||
160 | } | 147 | } |
161 | EXPORT_SYMBOL(dm_snap_cow); | 148 | EXPORT_SYMBOL(dm_snap_cow); |
162 | 149 | ||
163 | static struct workqueue_struct *ksnapd; | ||
164 | static void flush_queued_bios(struct work_struct *work); | ||
165 | |||
166 | static sector_t chunk_to_sector(struct dm_exception_store *store, | 150 | static sector_t chunk_to_sector(struct dm_exception_store *store, |
167 | chunk_t chunk) | 151 | chunk_t chunk) |
168 | { | 152 | { |
@@ -706,8 +690,6 @@ static int dm_add_exception(void *context, chunk_t old, chunk_t new) | |||
706 | return 0; | 690 | return 0; |
707 | } | 691 | } |
708 | 692 | ||
709 | #define min_not_zero(l, r) (((l) == 0) ? (r) : (((r) == 0) ? (l) : min(l, r))) | ||
710 | |||
711 | /* | 693 | /* |
712 | * Return a minimum chunk size of all snapshots that have the specified origin. | 694 | * Return a minimum chunk size of all snapshots that have the specified origin. |
713 | * Return zero if the origin has no snapshots. | 695 | * Return zero if the origin has no snapshots. |
@@ -1093,7 +1075,7 @@ static int snapshot_ctr(struct dm_target *ti, unsigned int argc, char **argv) | |||
1093 | argv++; | 1075 | argv++; |
1094 | argc--; | 1076 | argc--; |
1095 | 1077 | ||
1096 | r = dm_get_device(ti, cow_path, FMODE_READ | FMODE_WRITE, &s->cow); | 1078 | r = dm_get_device(ti, cow_path, dm_table_get_mode(ti->table), &s->cow); |
1097 | if (r) { | 1079 | if (r) { |
1098 | ti->error = "Cannot get COW device"; | 1080 | ti->error = "Cannot get COW device"; |
1099 | goto bad_cow; | 1081 | goto bad_cow; |
@@ -1112,7 +1094,6 @@ static int snapshot_ctr(struct dm_target *ti, unsigned int argc, char **argv) | |||
1112 | s->ti = ti; | 1094 | s->ti = ti; |
1113 | s->valid = 1; | 1095 | s->valid = 1; |
1114 | s->active = 0; | 1096 | s->active = 0; |
1115 | s->suspended = 0; | ||
1116 | atomic_set(&s->pending_exceptions_count, 0); | 1097 | atomic_set(&s->pending_exceptions_count, 0); |
1117 | init_rwsem(&s->lock); | 1098 | init_rwsem(&s->lock); |
1118 | INIT_LIST_HEAD(&s->list); | 1099 | INIT_LIST_HEAD(&s->list); |
@@ -1130,8 +1111,9 @@ static int snapshot_ctr(struct dm_target *ti, unsigned int argc, char **argv) | |||
1130 | goto bad_hash_tables; | 1111 | goto bad_hash_tables; |
1131 | } | 1112 | } |
1132 | 1113 | ||
1133 | r = dm_kcopyd_client_create(SNAPSHOT_PAGES, &s->kcopyd_client); | 1114 | s->kcopyd_client = dm_kcopyd_client_create(); |
1134 | if (r) { | 1115 | if (IS_ERR(s->kcopyd_client)) { |
1116 | r = PTR_ERR(s->kcopyd_client); | ||
1135 | ti->error = "Could not create kcopyd client"; | 1117 | ti->error = "Could not create kcopyd client"; |
1136 | goto bad_kcopyd; | 1118 | goto bad_kcopyd; |
1137 | } | 1119 | } |
@@ -1155,9 +1137,6 @@ static int snapshot_ctr(struct dm_target *ti, unsigned int argc, char **argv) | |||
1155 | 1137 | ||
1156 | spin_lock_init(&s->tracked_chunk_lock); | 1138 | spin_lock_init(&s->tracked_chunk_lock); |
1157 | 1139 | ||
1158 | bio_list_init(&s->queued_bios); | ||
1159 | INIT_WORK(&s->queued_bios_work, flush_queued_bios); | ||
1160 | |||
1161 | ti->private = s; | 1140 | ti->private = s; |
1162 | ti->num_flush_requests = num_flush_requests; | 1141 | ti->num_flush_requests = num_flush_requests; |
1163 | 1142 | ||
@@ -1281,8 +1260,6 @@ static void snapshot_dtr(struct dm_target *ti) | |||
1281 | struct dm_snapshot *s = ti->private; | 1260 | struct dm_snapshot *s = ti->private; |
1282 | struct dm_snapshot *snap_src = NULL, *snap_dest = NULL; | 1261 | struct dm_snapshot *snap_src = NULL, *snap_dest = NULL; |
1283 | 1262 | ||
1284 | flush_workqueue(ksnapd); | ||
1285 | |||
1286 | down_read(&_origins_lock); | 1263 | down_read(&_origins_lock); |
1287 | /* Check whether exception handover must be cancelled */ | 1264 | /* Check whether exception handover must be cancelled */ |
1288 | (void) __find_snapshots_sharing_cow(s, &snap_src, &snap_dest, NULL); | 1265 | (void) __find_snapshots_sharing_cow(s, &snap_src, &snap_dest, NULL); |
@@ -1344,20 +1321,6 @@ static void flush_bios(struct bio *bio) | |||
1344 | } | 1321 | } |
1345 | } | 1322 | } |
1346 | 1323 | ||
1347 | static void flush_queued_bios(struct work_struct *work) | ||
1348 | { | ||
1349 | struct dm_snapshot *s = | ||
1350 | container_of(work, struct dm_snapshot, queued_bios_work); | ||
1351 | struct bio *queued_bios; | ||
1352 | unsigned long flags; | ||
1353 | |||
1354 | spin_lock_irqsave(&s->pe_lock, flags); | ||
1355 | queued_bios = bio_list_get(&s->queued_bios); | ||
1356 | spin_unlock_irqrestore(&s->pe_lock, flags); | ||
1357 | |||
1358 | flush_bios(queued_bios); | ||
1359 | } | ||
1360 | |||
1361 | static int do_origin(struct dm_dev *origin, struct bio *bio); | 1324 | static int do_origin(struct dm_dev *origin, struct bio *bio); |
1362 | 1325 | ||
1363 | /* | 1326 | /* |
@@ -1587,7 +1550,7 @@ static int snapshot_map(struct dm_target *ti, struct bio *bio, | |||
1587 | chunk_t chunk; | 1550 | chunk_t chunk; |
1588 | struct dm_snap_pending_exception *pe = NULL; | 1551 | struct dm_snap_pending_exception *pe = NULL; |
1589 | 1552 | ||
1590 | if (unlikely(bio_empty_barrier(bio))) { | 1553 | if (bio->bi_rw & REQ_FLUSH) { |
1591 | bio->bi_bdev = s->cow->bdev; | 1554 | bio->bi_bdev = s->cow->bdev; |
1592 | return DM_MAPIO_REMAPPED; | 1555 | return DM_MAPIO_REMAPPED; |
1593 | } | 1556 | } |
@@ -1691,7 +1654,7 @@ static int snapshot_merge_map(struct dm_target *ti, struct bio *bio, | |||
1691 | int r = DM_MAPIO_REMAPPED; | 1654 | int r = DM_MAPIO_REMAPPED; |
1692 | chunk_t chunk; | 1655 | chunk_t chunk; |
1693 | 1656 | ||
1694 | if (unlikely(bio_empty_barrier(bio))) { | 1657 | if (bio->bi_rw & REQ_FLUSH) { |
1695 | if (!map_context->target_request_nr) | 1658 | if (!map_context->target_request_nr) |
1696 | bio->bi_bdev = s->origin->bdev; | 1659 | bio->bi_bdev = s->origin->bdev; |
1697 | else | 1660 | else |
@@ -1762,15 +1725,6 @@ static void snapshot_merge_presuspend(struct dm_target *ti) | |||
1762 | stop_merge(s); | 1725 | stop_merge(s); |
1763 | } | 1726 | } |
1764 | 1727 | ||
1765 | static void snapshot_postsuspend(struct dm_target *ti) | ||
1766 | { | ||
1767 | struct dm_snapshot *s = ti->private; | ||
1768 | |||
1769 | down_write(&s->lock); | ||
1770 | s->suspended = 1; | ||
1771 | up_write(&s->lock); | ||
1772 | } | ||
1773 | |||
1774 | static int snapshot_preresume(struct dm_target *ti) | 1728 | static int snapshot_preresume(struct dm_target *ti) |
1775 | { | 1729 | { |
1776 | int r = 0; | 1730 | int r = 0; |
@@ -1785,7 +1739,7 @@ static int snapshot_preresume(struct dm_target *ti) | |||
1785 | DMERR("Unable to resume snapshot source until " | 1739 | DMERR("Unable to resume snapshot source until " |
1786 | "handover completes."); | 1740 | "handover completes."); |
1787 | r = -EINVAL; | 1741 | r = -EINVAL; |
1788 | } else if (!snap_src->suspended) { | 1742 | } else if (!dm_suspended(snap_src->ti)) { |
1789 | DMERR("Unable to perform snapshot handover until " | 1743 | DMERR("Unable to perform snapshot handover until " |
1790 | "source is suspended."); | 1744 | "source is suspended."); |
1791 | r = -EINVAL; | 1745 | r = -EINVAL; |
@@ -1818,7 +1772,6 @@ static void snapshot_resume(struct dm_target *ti) | |||
1818 | 1772 | ||
1819 | down_write(&s->lock); | 1773 | down_write(&s->lock); |
1820 | s->active = 1; | 1774 | s->active = 1; |
1821 | s->suspended = 0; | ||
1822 | up_write(&s->lock); | 1775 | up_write(&s->lock); |
1823 | } | 1776 | } |
1824 | 1777 | ||
@@ -2135,7 +2088,7 @@ static int origin_map(struct dm_target *ti, struct bio *bio, | |||
2135 | struct dm_dev *dev = ti->private; | 2088 | struct dm_dev *dev = ti->private; |
2136 | bio->bi_bdev = dev->bdev; | 2089 | bio->bi_bdev = dev->bdev; |
2137 | 2090 | ||
2138 | if (unlikely(bio_empty_barrier(bio))) | 2091 | if (bio->bi_rw & REQ_FLUSH) |
2139 | return DM_MAPIO_REMAPPED; | 2092 | return DM_MAPIO_REMAPPED; |
2140 | 2093 | ||
2141 | /* Only tell snapshots if this is a write */ | 2094 | /* Only tell snapshots if this is a write */ |
@@ -2196,7 +2149,7 @@ static int origin_iterate_devices(struct dm_target *ti, | |||
2196 | 2149 | ||
2197 | static struct target_type origin_target = { | 2150 | static struct target_type origin_target = { |
2198 | .name = "snapshot-origin", | 2151 | .name = "snapshot-origin", |
2199 | .version = {1, 7, 0}, | 2152 | .version = {1, 7, 1}, |
2200 | .module = THIS_MODULE, | 2153 | .module = THIS_MODULE, |
2201 | .ctr = origin_ctr, | 2154 | .ctr = origin_ctr, |
2202 | .dtr = origin_dtr, | 2155 | .dtr = origin_dtr, |
@@ -2209,13 +2162,12 @@ static struct target_type origin_target = { | |||
2209 | 2162 | ||
2210 | static struct target_type snapshot_target = { | 2163 | static struct target_type snapshot_target = { |
2211 | .name = "snapshot", | 2164 | .name = "snapshot", |
2212 | .version = {1, 9, 0}, | 2165 | .version = {1, 10, 0}, |
2213 | .module = THIS_MODULE, | 2166 | .module = THIS_MODULE, |
2214 | .ctr = snapshot_ctr, | 2167 | .ctr = snapshot_ctr, |
2215 | .dtr = snapshot_dtr, | 2168 | .dtr = snapshot_dtr, |
2216 | .map = snapshot_map, | 2169 | .map = snapshot_map, |
2217 | .end_io = snapshot_end_io, | 2170 | .end_io = snapshot_end_io, |
2218 | .postsuspend = snapshot_postsuspend, | ||
2219 | .preresume = snapshot_preresume, | 2171 | .preresume = snapshot_preresume, |
2220 | .resume = snapshot_resume, | 2172 | .resume = snapshot_resume, |
2221 | .status = snapshot_status, | 2173 | .status = snapshot_status, |
@@ -2224,14 +2176,13 @@ static struct target_type snapshot_target = { | |||
2224 | 2176 | ||
2225 | static struct target_type merge_target = { | 2177 | static struct target_type merge_target = { |
2226 | .name = dm_snapshot_merge_target_name, | 2178 | .name = dm_snapshot_merge_target_name, |
2227 | .version = {1, 0, 0}, | 2179 | .version = {1, 1, 0}, |
2228 | .module = THIS_MODULE, | 2180 | .module = THIS_MODULE, |
2229 | .ctr = snapshot_ctr, | 2181 | .ctr = snapshot_ctr, |
2230 | .dtr = snapshot_dtr, | 2182 | .dtr = snapshot_dtr, |
2231 | .map = snapshot_merge_map, | 2183 | .map = snapshot_merge_map, |
2232 | .end_io = snapshot_end_io, | 2184 | .end_io = snapshot_end_io, |
2233 | .presuspend = snapshot_merge_presuspend, | 2185 | .presuspend = snapshot_merge_presuspend, |
2234 | .postsuspend = snapshot_postsuspend, | ||
2235 | .preresume = snapshot_preresume, | 2186 | .preresume = snapshot_preresume, |
2236 | .resume = snapshot_merge_resume, | 2187 | .resume = snapshot_merge_resume, |
2237 | .status = snapshot_status, | 2188 | .status = snapshot_status, |
@@ -2293,17 +2244,8 @@ static int __init dm_snapshot_init(void) | |||
2293 | goto bad_tracked_chunk_cache; | 2244 | goto bad_tracked_chunk_cache; |
2294 | } | 2245 | } |
2295 | 2246 | ||
2296 | ksnapd = create_singlethread_workqueue("ksnapd"); | ||
2297 | if (!ksnapd) { | ||
2298 | DMERR("Failed to create ksnapd workqueue."); | ||
2299 | r = -ENOMEM; | ||
2300 | goto bad_pending_pool; | ||
2301 | } | ||
2302 | |||
2303 | return 0; | 2247 | return 0; |
2304 | 2248 | ||
2305 | bad_pending_pool: | ||
2306 | kmem_cache_destroy(tracked_chunk_cache); | ||
2307 | bad_tracked_chunk_cache: | 2249 | bad_tracked_chunk_cache: |
2308 | kmem_cache_destroy(pending_cache); | 2250 | kmem_cache_destroy(pending_cache); |
2309 | bad_pending_cache: | 2251 | bad_pending_cache: |
@@ -2324,8 +2266,6 @@ bad_register_snapshot_target: | |||
2324 | 2266 | ||
2325 | static void __exit dm_snapshot_exit(void) | 2267 | static void __exit dm_snapshot_exit(void) |
2326 | { | 2268 | { |
2327 | destroy_workqueue(ksnapd); | ||
2328 | |||
2329 | dm_unregister_target(&snapshot_target); | 2269 | dm_unregister_target(&snapshot_target); |
2330 | dm_unregister_target(&origin_target); | 2270 | dm_unregister_target(&origin_target); |
2331 | dm_unregister_target(&merge_target); | 2271 | dm_unregister_target(&merge_target); |