Login
[x]
Log in using an account from:
Fedora Account System
Red Hat Associate
Red Hat Customer
Or login using a Red Hat Bugzilla account
Forgot Password
Login:
Hide Forgot
Create an Account
Red Hat Bugzilla – Attachment 863191 Details for
Bug 1065051
A few races/bugs in the thinp code compromise the ability to successfully resize a full thin-pool
[?]
New
Simple Search
Advanced Search
My Links
Browse
Requests
Reports
Current State
Search
Tabular reports
Graphical reports
Duplicates
Other Reports
User Changes
Plotly Reports
Bug Status
Bug Severity
Non-Defaults
|
Product Dashboard
Help
Page Help!
Bug Writing Guidelines
What's new
Browser Support Policy
5.0.4.rh83 Release notes
FAQ
Guides index
User guide
Web Services
Contact
Legal
This site requires JavaScript to be enabled to function correctly, please enable it.
Patch 1
for-3.14-18-20-dm-thin-fix-pool_preresume-resize-with-heavy-IO-races.patch (text/plain), 6.19 KB, created by
Zdenek Kabelac
on 2014-02-14 10:12:09 UTC
(
hide
)
Description:
Patch 1
Filename:
MIME Type:
Creator:
Zdenek Kabelac
Created:
2014-02-14 10:12:09 UTC
Size:
6.19 KB
patch
obsolete
>diff --git a/drivers/md/dm-thin-metadata.c b/drivers/md/dm-thin-metadata.c >index 7da3476..974e2cf 100644 >--- a/drivers/md/dm-thin-metadata.c >+++ b/drivers/md/dm-thin-metadata.c >@@ -1586,6 +1586,30 @@ int dm_pool_get_free_metadata_block_count(struct dm_pool_metadata *pmd, > return r; > } > >+int dm_pool_is_out_of_space(struct dm_pool_metadata *pmd, bool *result) >+{ >+ int r; >+ dm_block_t free_blocks; >+ >+ *result = false; >+ >+ r = dm_pool_get_free_block_count(pmd, &free_blocks); >+ if (r) >+ return r; >+ if (!free_blocks) { >+ *result = true; >+ return 0; >+ } >+ >+ r = dm_pool_get_free_metadata_block_count(pmd, &free_blocks); >+ if (r) >+ return r; >+ if (!free_blocks) >+ *result = true; >+ >+ return 0; >+} >+ > int dm_pool_get_metadata_dev_size(struct dm_pool_metadata *pmd, > dm_block_t *result) > { >@@ -1709,6 +1733,17 @@ int dm_pool_resize_metadata_dev(struct dm_pool_metadata *pmd, dm_block_t new_cou > return r; > } > >+bool dm_pool_metadata_is_read_only(struct dm_pool_metadata *pmd) >+{ >+ bool r; >+ >+ down_read(&pmd->root_lock); >+ r = pmd->read_only; >+ up_read(&pmd->root_lock); >+ >+ return r; >+} >+ > void dm_pool_metadata_read_only(struct dm_pool_metadata *pmd) > { > down_write(&pmd->root_lock); >diff --git a/drivers/md/dm-thin-metadata.h b/drivers/md/dm-thin-metadata.h >index 9a36856..dcbd08c 100644 >--- a/drivers/md/dm-thin-metadata.h >+++ b/drivers/md/dm-thin-metadata.h >@@ -177,6 +177,8 @@ int dm_pool_get_free_metadata_block_count(struct dm_pool_metadata *pmd, > int dm_pool_get_metadata_dev_size(struct dm_pool_metadata *pmd, > dm_block_t *result); > >+int dm_pool_is_out_of_space(struct dm_pool_metadata *pmd, bool *result); >+ > int dm_pool_get_data_block_size(struct dm_pool_metadata *pmd, sector_t *result); > > int dm_pool_get_data_dev_size(struct dm_pool_metadata *pmd, dm_block_t *result); >@@ -194,6 +196,7 @@ int dm_pool_resize_metadata_dev(struct dm_pool_metadata *pmd, dm_block_t new_siz > * Flicks the underlying block manager into read only mode, so you know > * that nothing is changing. > */ >+bool dm_pool_metadata_is_read_only(struct dm_pool_metadata *pmd); > void dm_pool_metadata_read_only(struct dm_pool_metadata *pmd); > void dm_pool_metadata_read_write(struct dm_pool_metadata *pmd); > >diff --git a/drivers/md/dm-thin.c b/drivers/md/dm-thin.c >index 4a2432a..53dcdfb 100644 >--- a/drivers/md/dm-thin.c >+++ b/drivers/md/dm-thin.c >@@ -891,22 +891,43 @@ static void schedule_zero(struct thin_c *tc, dm_block_t virt_block, > } > } > >+static int __commit(struct pool *pool) >+{ >+ int r = dm_pool_commit_metadata(pool->pmd); >+ if (r) >+ metadata_operation_failed(pool, "dm_pool_commit_metadata", r); >+ >+ return r; >+} >+ >+/* >+ * Commit that is confined to the metadata superblock due to pool >+ * being in PM_READ_ONLY mode (read-only process_* functions). >+ * A non-zero return indicates metadata is not writable. >+ */ >+static int commit_metadata_superblock(struct pool *pool) >+{ >+ WARN_ON_ONCE(get_pool_mode(pool) != PM_READ_ONLY); >+ >+ if (dm_pool_metadata_is_read_only(pool->pmd)) { >+ DMERR_LIMIT("%s: commit failed: pool metadata is not writable", >+ dm_device_name(pool->pool_md)); >+ return -EINVAL; >+ } >+ >+ return __commit(pool); >+} >+ > /* > * A non-zero return indicates read_only or fail_io mode. > * Many callers don't care about the return value. > */ > static int commit(struct pool *pool) > { >- int r; >- > if (get_pool_mode(pool) != PM_WRITE) > return -EINVAL; > >- r = dm_pool_commit_metadata(pool->pmd); >- if (r) >- metadata_operation_failed(pool, "dm_pool_commit_metadata", r); >- >- return r; >+ return __commit(pool); > } > > static void check_low_water_mark(struct pool *pool, dm_block_t free_blocks) >@@ -1424,7 +1445,11 @@ static void set_pool_mode(struct pool *pool, enum pool_mode new_mode) > new_mode = PM_FAIL; > set_pool_mode(pool, new_mode); > } else { >- dm_pool_metadata_read_only(pool->pmd); >+ bool out_of_space; >+ if (!dm_pool_is_out_of_space(pool->pmd, &out_of_space) && out_of_space) >+ dm_pool_metadata_read_write(pool->pmd); >+ else >+ dm_pool_metadata_read_only(pool->pmd); > pool->process_bio = process_bio_read_only; > pool->process_discard = process_discard; > pool->process_prepared_mapping = process_prepared_mapping_fail; >@@ -1701,12 +1726,17 @@ static int bind_control_target(struct pool *pool, struct dm_target *ti) > /* > * If we were in PM_FAIL mode, rollback of metadata failed. We're > * not going to recover without a thin_repair. So we never let the >- * pool move out of the old mode. On the other hand a PM_READ_ONLY >- * may have been due to a lack of metadata or data space, and may >- * now work (ie. if the underlying devices have been resized). >+ * pool move out of the old mode. Similarly, if in PM_READ_ONLY mode >+ * and the pool doesn't have free space we must not switch modes here; >+ * pool_preresume() will transition to PM_WRITE mode if a resize succeeds. > */ > if (old_mode == PM_FAIL) > new_mode = old_mode; >+ else if (old_mode == PM_READ_ONLY) { >+ bool out_of_space; >+ if (!dm_pool_is_out_of_space(pool->pmd, &out_of_space) && out_of_space) >+ new_mode = old_mode; >+ } > > set_pool_mode(pool, new_mode); > >@@ -2317,6 +2347,7 @@ static int pool_preresume(struct dm_target *ti) > bool need_commit1, need_commit2; > struct pool_c *pt = ti->private; > struct pool *pool = pt->pool; >+ bool out_of_space = false; > > /* > * Take control of the pool object. >@@ -2325,6 +2356,12 @@ static int pool_preresume(struct dm_target *ti) > if (r) > return r; > >+ if (get_pool_mode(pool) == PM_READ_ONLY) { >+ r = dm_pool_is_out_of_space(pool->pmd, &out_of_space); >+ if (r) >+ metadata_operation_failed(pool, "dm_pool_is_out_of_space", r); >+ } >+ > r = maybe_resize_data_dev(ti, &need_commit1); > if (r) > return r; >@@ -2333,8 +2370,23 @@ static int pool_preresume(struct dm_target *ti) > if (r) > return r; > >- if (need_commit1 || need_commit2) >- (void) commit(pool); >+ if (need_commit1 || need_commit2) { >+ if (out_of_space) { >+ /* >+ * Must update metadata's superblock despite read-only mode. >+ */ >+ r = commit_metadata_superblock(pool); >+ if (r || pt->requested_pf.mode == PM_READ_ONLY) >+ dm_pool_metadata_read_only(pool->pmd); >+ else { >+ /* >+ * If resize succeeded transition the pool to write mode. >+ */ >+ set_pool_mode(pool, PM_WRITE); >+ } >+ } else >+ (void) commit(pool); >+ } > > return 0; > }
You cannot view the attachment while viewing its details because your browser does not support IFRAMEs.
View the attachment on a separate page
.
View Attachment As Raw
Actions:
View
Attachments on
bug 1065051
: 863191 |
863192
|
863524