diff options
Diffstat (limited to 'drivers/md/dm-thin.c')
| -rw-r--r-- | drivers/md/dm-thin.c | 44 |
1 files changed, 37 insertions, 7 deletions
diff --git a/drivers/md/dm-thin.c b/drivers/md/dm-thin.c index c33f61a4cc28..1c50c580215c 100644 --- a/drivers/md/dm-thin.c +++ b/drivers/md/dm-thin.c | |||
| @@ -18,6 +18,7 @@ | |||
| 18 | #include <linux/init.h> | 18 | #include <linux/init.h> |
| 19 | #include <linux/module.h> | 19 | #include <linux/module.h> |
| 20 | #include <linux/slab.h> | 20 | #include <linux/slab.h> |
| 21 | #include <linux/vmalloc.h> | ||
| 21 | #include <linux/sort.h> | 22 | #include <linux/sort.h> |
| 22 | #include <linux/rbtree.h> | 23 | #include <linux/rbtree.h> |
| 23 | 24 | ||
| @@ -268,7 +269,7 @@ struct pool { | |||
| 268 | process_mapping_fn process_prepared_mapping; | 269 | process_mapping_fn process_prepared_mapping; |
| 269 | process_mapping_fn process_prepared_discard; | 270 | process_mapping_fn process_prepared_discard; |
| 270 | 271 | ||
| 271 | struct dm_bio_prison_cell *cell_sort_array[CELL_SORT_ARRAY_SIZE]; | 272 | struct dm_bio_prison_cell **cell_sort_array; |
| 272 | }; | 273 | }; |
| 273 | 274 | ||
| 274 | static enum pool_mode get_pool_mode(struct pool *pool); | 275 | static enum pool_mode get_pool_mode(struct pool *pool); |
| @@ -2281,18 +2282,23 @@ static void do_waker(struct work_struct *ws) | |||
| 2281 | queue_delayed_work(pool->wq, &pool->waker, COMMIT_PERIOD); | 2282 | queue_delayed_work(pool->wq, &pool->waker, COMMIT_PERIOD); |
| 2282 | } | 2283 | } |
| 2283 | 2284 | ||
| 2285 | static void notify_of_pool_mode_change_to_oods(struct pool *pool); | ||
| 2286 | |||
| 2284 | /* | 2287 | /* |
| 2285 | * We're holding onto IO to allow userland time to react. After the | 2288 | * We're holding onto IO to allow userland time to react. After the |
| 2286 | * timeout either the pool will have been resized (and thus back in | 2289 | * timeout either the pool will have been resized (and thus back in |
| 2287 | * PM_WRITE mode), or we degrade to PM_READ_ONLY and start erroring IO. | 2290 | * PM_WRITE mode), or we degrade to PM_OUT_OF_DATA_SPACE w/ error_if_no_space. |
| 2288 | */ | 2291 | */ |
| 2289 | static void do_no_space_timeout(struct work_struct *ws) | 2292 | static void do_no_space_timeout(struct work_struct *ws) |
| 2290 | { | 2293 | { |
| 2291 | struct pool *pool = container_of(to_delayed_work(ws), struct pool, | 2294 | struct pool *pool = container_of(to_delayed_work(ws), struct pool, |
| 2292 | no_space_timeout); | 2295 | no_space_timeout); |
| 2293 | 2296 | ||
| 2294 | if (get_pool_mode(pool) == PM_OUT_OF_DATA_SPACE && !pool->pf.error_if_no_space) | 2297 | if (get_pool_mode(pool) == PM_OUT_OF_DATA_SPACE && !pool->pf.error_if_no_space) { |
| 2295 | set_pool_mode(pool, PM_READ_ONLY); | 2298 | pool->pf.error_if_no_space = true; |
| 2299 | notify_of_pool_mode_change_to_oods(pool); | ||
| 2300 | error_retry_list(pool); | ||
| 2301 | } | ||
| 2296 | } | 2302 | } |
| 2297 | 2303 | ||
| 2298 | /*----------------------------------------------------------------*/ | 2304 | /*----------------------------------------------------------------*/ |
| @@ -2370,6 +2376,14 @@ static void notify_of_pool_mode_change(struct pool *pool, const char *new_mode) | |||
| 2370 | dm_device_name(pool->pool_md), new_mode); | 2376 | dm_device_name(pool->pool_md), new_mode); |
| 2371 | } | 2377 | } |
| 2372 | 2378 | ||
| 2379 | static void notify_of_pool_mode_change_to_oods(struct pool *pool) | ||
| 2380 | { | ||
| 2381 | if (!pool->pf.error_if_no_space) | ||
| 2382 | notify_of_pool_mode_change(pool, "out-of-data-space (queue IO)"); | ||
| 2383 | else | ||
| 2384 | notify_of_pool_mode_change(pool, "out-of-data-space (error IO)"); | ||
| 2385 | } | ||
| 2386 | |||
| 2373 | static bool passdown_enabled(struct pool_c *pt) | 2387 | static bool passdown_enabled(struct pool_c *pt) |
| 2374 | { | 2388 | { |
| 2375 | return pt->adjusted_pf.discard_passdown; | 2389 | return pt->adjusted_pf.discard_passdown; |
| @@ -2454,7 +2468,7 @@ static void set_pool_mode(struct pool *pool, enum pool_mode new_mode) | |||
| 2454 | * frequently seeing this mode. | 2468 | * frequently seeing this mode. |
| 2455 | */ | 2469 | */ |
| 2456 | if (old_mode != new_mode) | 2470 | if (old_mode != new_mode) |
| 2457 | notify_of_pool_mode_change(pool, "out-of-data-space"); | 2471 | notify_of_pool_mode_change_to_oods(pool); |
| 2458 | pool->process_bio = process_bio_read_only; | 2472 | pool->process_bio = process_bio_read_only; |
| 2459 | pool->process_discard = process_discard_bio; | 2473 | pool->process_discard = process_discard_bio; |
| 2460 | pool->process_cell = process_cell_read_only; | 2474 | pool->process_cell = process_cell_read_only; |
| @@ -2777,6 +2791,7 @@ static void __pool_destroy(struct pool *pool) | |||
| 2777 | { | 2791 | { |
| 2778 | __pool_table_remove(pool); | 2792 | __pool_table_remove(pool); |
| 2779 | 2793 | ||
| 2794 | vfree(pool->cell_sort_array); | ||
| 2780 | if (dm_pool_metadata_close(pool->pmd) < 0) | 2795 | if (dm_pool_metadata_close(pool->pmd) < 0) |
| 2781 | DMWARN("%s: dm_pool_metadata_close() failed.", __func__); | 2796 | DMWARN("%s: dm_pool_metadata_close() failed.", __func__); |
| 2782 | 2797 | ||
| @@ -2889,6 +2904,13 @@ static struct pool *pool_create(struct mapped_device *pool_md, | |||
| 2889 | goto bad_mapping_pool; | 2904 | goto bad_mapping_pool; |
| 2890 | } | 2905 | } |
| 2891 | 2906 | ||
| 2907 | pool->cell_sort_array = vmalloc(sizeof(*pool->cell_sort_array) * CELL_SORT_ARRAY_SIZE); | ||
| 2908 | if (!pool->cell_sort_array) { | ||
| 2909 | *error = "Error allocating cell sort array"; | ||
| 2910 | err_p = ERR_PTR(-ENOMEM); | ||
| 2911 | goto bad_sort_array; | ||
| 2912 | } | ||
| 2913 | |||
| 2892 | pool->ref_count = 1; | 2914 | pool->ref_count = 1; |
| 2893 | pool->last_commit_jiffies = jiffies; | 2915 | pool->last_commit_jiffies = jiffies; |
| 2894 | pool->pool_md = pool_md; | 2916 | pool->pool_md = pool_md; |
| @@ -2897,6 +2919,8 @@ static struct pool *pool_create(struct mapped_device *pool_md, | |||
| 2897 | 2919 | ||
| 2898 | return pool; | 2920 | return pool; |
| 2899 | 2921 | ||
| 2922 | bad_sort_array: | ||
| 2923 | mempool_destroy(pool->mapping_pool); | ||
| 2900 | bad_mapping_pool: | 2924 | bad_mapping_pool: |
| 2901 | dm_deferred_set_destroy(pool->all_io_ds); | 2925 | dm_deferred_set_destroy(pool->all_io_ds); |
| 2902 | bad_all_io_ds: | 2926 | bad_all_io_ds: |
| @@ -3714,6 +3738,7 @@ static void emit_flags(struct pool_features *pf, char *result, | |||
| 3714 | * Status line is: | 3738 | * Status line is: |
| 3715 | * <transaction id> <used metadata sectors>/<total metadata sectors> | 3739 | * <transaction id> <used metadata sectors>/<total metadata sectors> |
| 3716 | * <used data sectors>/<total data sectors> <held metadata root> | 3740 | * <used data sectors>/<total data sectors> <held metadata root> |
| 3741 | * <pool mode> <discard config> <no space config> <needs_check> | ||
| 3717 | */ | 3742 | */ |
| 3718 | static void pool_status(struct dm_target *ti, status_type_t type, | 3743 | static void pool_status(struct dm_target *ti, status_type_t type, |
| 3719 | unsigned status_flags, char *result, unsigned maxlen) | 3744 | unsigned status_flags, char *result, unsigned maxlen) |
| @@ -3815,6 +3840,11 @@ static void pool_status(struct dm_target *ti, status_type_t type, | |||
| 3815 | else | 3840 | else |
| 3816 | DMEMIT("queue_if_no_space "); | 3841 | DMEMIT("queue_if_no_space "); |
| 3817 | 3842 | ||
| 3843 | if (dm_pool_metadata_needs_check(pool->pmd)) | ||
| 3844 | DMEMIT("needs_check "); | ||
| 3845 | else | ||
| 3846 | DMEMIT("- "); | ||
| 3847 | |||
| 3818 | break; | 3848 | break; |
| 3819 | 3849 | ||
| 3820 | case STATUSTYPE_TABLE: | 3850 | case STATUSTYPE_TABLE: |
| @@ -3918,7 +3948,7 @@ static struct target_type pool_target = { | |||
| 3918 | .name = "thin-pool", | 3948 | .name = "thin-pool", |
| 3919 | .features = DM_TARGET_SINGLETON | DM_TARGET_ALWAYS_WRITEABLE | | 3949 | .features = DM_TARGET_SINGLETON | DM_TARGET_ALWAYS_WRITEABLE | |
| 3920 | DM_TARGET_IMMUTABLE, | 3950 | DM_TARGET_IMMUTABLE, |
| 3921 | .version = {1, 15, 0}, | 3951 | .version = {1, 16, 0}, |
| 3922 | .module = THIS_MODULE, | 3952 | .module = THIS_MODULE, |
| 3923 | .ctr = pool_ctr, | 3953 | .ctr = pool_ctr, |
| 3924 | .dtr = pool_dtr, | 3954 | .dtr = pool_dtr, |
| @@ -4305,7 +4335,7 @@ static void thin_io_hints(struct dm_target *ti, struct queue_limits *limits) | |||
| 4305 | 4335 | ||
| 4306 | static struct target_type thin_target = { | 4336 | static struct target_type thin_target = { |
| 4307 | .name = "thin", | 4337 | .name = "thin", |
| 4308 | .version = {1, 15, 0}, | 4338 | .version = {1, 16, 0}, |
| 4309 | .module = THIS_MODULE, | 4339 | .module = THIS_MODULE, |
| 4310 | .ctr = thin_ctr, | 4340 | .ctr = thin_ctr, |
| 4311 | .dtr = thin_dtr, | 4341 | .dtr = thin_dtr, |
