|
@@ -195,7 +195,7 @@ static void throttle_unlock(struct throttle *t)
|
|
|
struct dm_thin_new_mapping;
|
|
|
|
|
|
/*
|
|
|
- * The pool runs in 4 modes. Ordered in degraded order for comparisons.
|
|
|
+ * The pool runs in various modes. Ordered in degraded order for comparisons.
|
|
|
*/
|
|
|
enum pool_mode {
|
|
|
PM_WRITE, /* metadata may be changed */
|
|
@@ -282,9 +282,38 @@ struct pool {
|
|
|
mempool_t mapping_pool;
|
|
|
};
|
|
|
|
|
|
-static enum pool_mode get_pool_mode(struct pool *pool);
|
|
|
static void metadata_operation_failed(struct pool *pool, const char *op, int r);
|
|
|
|
|
|
+static enum pool_mode get_pool_mode(struct pool *pool)
|
|
|
+{
|
|
|
+ return pool->pf.mode;
|
|
|
+}
|
|
|
+
|
|
|
+static void notify_of_pool_mode_change(struct pool *pool)
|
|
|
+{
|
|
|
+ const char *descs[] = {
|
|
|
+ "write",
|
|
|
+ "out-of-data-space",
|
|
|
+ "read-only",
|
|
|
+ "read-only",
|
|
|
+ "fail"
|
|
|
+ };
|
|
|
+ const char *extra_desc = NULL;
|
|
|
+ enum pool_mode mode = get_pool_mode(pool);
|
|
|
+
|
|
|
+ if (mode == PM_OUT_OF_DATA_SPACE) {
|
|
|
+ if (!pool->pf.error_if_no_space)
|
|
|
+ extra_desc = " (queue IO)";
|
|
|
+ else
|
|
|
+ extra_desc = " (error IO)";
|
|
|
+ }
|
|
|
+
|
|
|
+ dm_table_event(pool->ti->table);
|
|
|
+ DMINFO("%s: switching pool to %s%s mode",
|
|
|
+ dm_device_name(pool->pool_md),
|
|
|
+ descs[(int)mode], extra_desc ? : "");
|
|
|
+}
|
|
|
+
|
|
|
/*
|
|
|
* Target context for a pool.
|
|
|
*/
|
|
@@ -2351,8 +2380,6 @@ static void do_waker(struct work_struct *ws)
|
|
|
queue_delayed_work(pool->wq, &pool->waker, COMMIT_PERIOD);
|
|
|
}
|
|
|
|
|
|
-static void notify_of_pool_mode_change_to_oods(struct pool *pool);
|
|
|
-
|
|
|
/*
|
|
|
* We're holding onto IO to allow userland time to react. After the
|
|
|
* timeout either the pool will have been resized (and thus back in
|
|
@@ -2365,7 +2392,7 @@ static void do_no_space_timeout(struct work_struct *ws)
|
|
|
|
|
|
if (get_pool_mode(pool) == PM_OUT_OF_DATA_SPACE && !pool->pf.error_if_no_space) {
|
|
|
pool->pf.error_if_no_space = true;
|
|
|
- notify_of_pool_mode_change_to_oods(pool);
|
|
|
+ notify_of_pool_mode_change(pool);
|
|
|
error_retry_list_with_code(pool, BLK_STS_NOSPC);
|
|
|
}
|
|
|
}
|
|
@@ -2433,26 +2460,6 @@ static void noflush_work(struct thin_c *tc, void (*fn)(struct work_struct *))
|
|
|
|
|
|
/*----------------------------------------------------------------*/
|
|
|
|
|
|
-static enum pool_mode get_pool_mode(struct pool *pool)
|
|
|
-{
|
|
|
- return pool->pf.mode;
|
|
|
-}
|
|
|
-
|
|
|
-static void notify_of_pool_mode_change(struct pool *pool, const char *new_mode)
|
|
|
-{
|
|
|
- dm_table_event(pool->ti->table);
|
|
|
- DMINFO("%s: switching pool to %s mode",
|
|
|
- dm_device_name(pool->pool_md), new_mode);
|
|
|
-}
|
|
|
-
|
|
|
-static void notify_of_pool_mode_change_to_oods(struct pool *pool)
|
|
|
-{
|
|
|
- if (!pool->pf.error_if_no_space)
|
|
|
- notify_of_pool_mode_change(pool, "out-of-data-space (queue IO)");
|
|
|
- else
|
|
|
- notify_of_pool_mode_change(pool, "out-of-data-space (error IO)");
|
|
|
-}
|
|
|
-
|
|
|
static bool passdown_enabled(struct pool_c *pt)
|
|
|
{
|
|
|
return pt->adjusted_pf.discard_passdown;
|
|
@@ -2501,8 +2508,6 @@ static void set_pool_mode(struct pool *pool, enum pool_mode new_mode)
|
|
|
|
|
|
switch (new_mode) {
|
|
|
case PM_FAIL:
|
|
|
- if (old_mode != new_mode)
|
|
|
- notify_of_pool_mode_change(pool, "failure");
|
|
|
dm_pool_metadata_read_only(pool->pmd);
|
|
|
pool->process_bio = process_bio_fail;
|
|
|
pool->process_discard = process_bio_fail;
|
|
@@ -2516,8 +2521,6 @@ static void set_pool_mode(struct pool *pool, enum pool_mode new_mode)
|
|
|
|
|
|
case PM_OUT_OF_METADATA_SPACE:
|
|
|
case PM_READ_ONLY:
|
|
|
- if (!is_read_only_pool_mode(old_mode))
|
|
|
- notify_of_pool_mode_change(pool, "read-only");
|
|
|
dm_pool_metadata_read_only(pool->pmd);
|
|
|
pool->process_bio = process_bio_read_only;
|
|
|
pool->process_discard = process_bio_success;
|
|
@@ -2538,8 +2541,6 @@ static void set_pool_mode(struct pool *pool, enum pool_mode new_mode)
|
|
|
* alarming rate. Adjust your low water mark if you're
|
|
|
* frequently seeing this mode.
|
|
|
*/
|
|
|
- if (old_mode != new_mode)
|
|
|
- notify_of_pool_mode_change_to_oods(pool);
|
|
|
pool->out_of_data_space = true;
|
|
|
pool->process_bio = process_bio_read_only;
|
|
|
pool->process_discard = process_discard_bio;
|
|
@@ -2552,8 +2553,6 @@ static void set_pool_mode(struct pool *pool, enum pool_mode new_mode)
|
|
|
break;
|
|
|
|
|
|
case PM_WRITE:
|
|
|
- if (old_mode != new_mode)
|
|
|
- notify_of_pool_mode_change(pool, "write");
|
|
|
if (old_mode == PM_OUT_OF_DATA_SPACE)
|
|
|
cancel_delayed_work_sync(&pool->no_space_timeout);
|
|
|
pool->out_of_data_space = false;
|
|
@@ -2573,6 +2572,9 @@ static void set_pool_mode(struct pool *pool, enum pool_mode new_mode)
|
|
|
* doesn't cause an unexpected mode transition on resume.
|
|
|
*/
|
|
|
pt->adjusted_pf.mode = new_mode;
|
|
|
+
|
|
|
+ if (old_mode != new_mode)
|
|
|
+ notify_of_pool_mode_change(pool);
|
|
|
}
|
|
|
|
|
|
static void abort_transaction(struct pool *pool)
|