|
@@ -27,6 +27,7 @@
|
|
|
#define MAPPING_POOL_SIZE 1024
|
|
|
#define PRISON_CELLS 1024
|
|
|
#define COMMIT_PERIOD HZ
|
|
|
+#define NO_SPACE_TIMEOUT (HZ * 60)
|
|
|
|
|
|
DECLARE_DM_KCOPYD_THROTTLE_WITH_MODULE_PARM(snapshot_copy_throttle,
|
|
|
"A percentage of time allocated for copy on write");
|
|
@@ -175,6 +176,7 @@ struct pool {
|
|
|
struct workqueue_struct *wq;
|
|
|
struct work_struct worker;
|
|
|
struct delayed_work waker;
|
|
|
+ struct delayed_work no_space_timeout;
|
|
|
|
|
|
unsigned long last_commit_jiffies;
|
|
|
unsigned ref_count;
|
|
@@ -1590,6 +1592,20 @@ static void do_waker(struct work_struct *ws)
|
|
|
queue_delayed_work(pool->wq, &pool->waker, COMMIT_PERIOD);
|
|
|
}
|
|
|
|
|
|
+/*
|
|
|
+ * 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
|
|
|
+ * PM_WRITE mode), or we degrade to PM_READ_ONLY and start erroring IO.
|
|
|
+ */
|
|
|
+static void do_no_space_timeout(struct work_struct *ws)
|
|
|
+{
|
|
|
+ struct pool *pool = container_of(to_delayed_work(ws), struct pool,
|
|
|
+ no_space_timeout);
|
|
|
+
|
|
|
+ if (get_pool_mode(pool) == PM_OUT_OF_DATA_SPACE && !pool->pf.error_if_no_space)
|
|
|
+ set_pool_mode(pool, PM_READ_ONLY);
|
|
|
+}
|
|
|
+
|
|
|
/*----------------------------------------------------------------*/
|
|
|
|
|
|
struct noflush_work {
|
|
@@ -1715,6 +1731,9 @@ static void set_pool_mode(struct pool *pool, enum pool_mode new_mode)
|
|
|
pool->process_discard = process_discard;
|
|
|
pool->process_prepared_mapping = process_prepared_mapping;
|
|
|
pool->process_prepared_discard = process_prepared_discard_passdown;
|
|
|
+
|
|
|
+ if (!pool->pf.error_if_no_space)
|
|
|
+ queue_delayed_work(pool->wq, &pool->no_space_timeout, NO_SPACE_TIMEOUT);
|
|
|
break;
|
|
|
|
|
|
case PM_WRITE:
|
|
@@ -2100,6 +2119,7 @@ static struct pool *pool_create(struct mapped_device *pool_md,
|
|
|
|
|
|
INIT_WORK(&pool->worker, do_worker);
|
|
|
INIT_DELAYED_WORK(&pool->waker, do_waker);
|
|
|
+ INIT_DELAYED_WORK(&pool->no_space_timeout, do_no_space_timeout);
|
|
|
spin_lock_init(&pool->lock);
|
|
|
bio_list_init(&pool->deferred_flush_bios);
|
|
|
INIT_LIST_HEAD(&pool->prepared_mappings);
|
|
@@ -2662,6 +2682,7 @@ static void pool_postsuspend(struct dm_target *ti)
|
|
|
struct pool *pool = pt->pool;
|
|
|
|
|
|
cancel_delayed_work(&pool->waker);
|
|
|
+ cancel_delayed_work(&pool->no_space_timeout);
|
|
|
flush_workqueue(pool->wq);
|
|
|
(void) commit(pool);
|
|
|
}
|