[Devel] [PATCH RHEL7 COMMIT] ploop: Be overprotective on discard
Konstantin Khorenko
khorenko at virtuozzo.com
Fri Mar 6 14:03:37 MSK 2020
The commit is pushed to "branch-rh7-3.10.0-1062.12.1.vz7.145.x-ovz" and will appear at https://src.openvz.org/scm/ovz/vzkernel.git
after rh7-3.10.0-1062.12.1.vz7.131.8
------>
commit db4ee42022c3c49a58b128b9a9aafa633a828ecc
Author: Kirill Tkhai <ktkhai at virtuozzo.com>
Date: Thu Mar 5 15:46:46 2020 +0300
ploop: Be overprotective on discard
Forced wait all discard requests before snapshot and grow.
Signed-off-by: Kirill Tkhai <ktkhai at virtuozzo.com>
khorenko@:
v2: make disable_and_wait_discard() be prepared to be run in parallel so
plo->discard_disabled_count could be > 1.
It's not the case for now (ploop_snapshot() and ploop_grow() cann't
run in parallel), but might become a case in the future.
=====================
Patchset description:
ploop: Be over protectable on discard
Forcedly wait and disable discard on snapshot and grow.
Kirill Tkhai (4):
ploop: Simplify check in ploop_fast_end_io()
ploop: Rename fast_path_waitq into pending_waitq
ploop: Rename bio_discard_inflight_reqs into discard_inflight_reqs
ploop: Be overprotective on discard
---
drivers/block/ploop/dev.c | 69 ++++++++++++++++++++++++++++++++++++++++++---
include/linux/ploop/ploop.h | 1 +
2 files changed, 66 insertions(+), 4 deletions(-)
diff --git a/drivers/block/ploop/dev.c b/drivers/block/ploop/dev.c
index 7836731223852..55ca57de61dbf 100644
--- a/drivers/block/ploop/dev.c
+++ b/drivers/block/ploop/dev.c
@@ -181,6 +181,41 @@ static void wait_fast_path_reqs(struct ploop_device *plo)
wait_event(plo->pending_waitq, fast_path_reqs_count(plo) == 0);
}
+static int discard_reqs_count(struct ploop_device *plo)
+{
+ int ret;
+
+ spin_lock_irq(&plo->lock);
+ ret = plo->discard_inflight_reqs;
+ spin_unlock_irq(&plo->lock);
+
+ return ret;
+}
+
+/* Returns 0 or -EINTR */
+static int disable_and_wait_discard(struct ploop_device *plo)
+{
+ int ret;
+
+ spin_lock_irq(&plo->lock);
+ plo->discard_disabled_count++;
+ spin_unlock_irq(&plo->lock);
+
+ ret = wait_event_interruptible(plo->pending_waitq,
+ discard_reqs_count(plo) == 0);
+ if (ret)
+ enable_discard(plo);
+
+ return ret;
+}
+
+static void enable_discard(struct ploop_device *plo)
+{
+ spin_lock_irq(&plo->lock);
+ WARN_ON_ONCE(plo->discard_disabled_count-- == 0);
+ spin_unlock_irq(&plo->lock);
+}
+
static void ploop_init_request(struct ploop_request *preq)
{
preq->eng_state = PLOOP_E_ENTRY;
@@ -2233,6 +2268,12 @@ static bool ploop_can_issue_discard(struct ploop_device *plo,
if (test_bit(PLOOP_S_NO_FALLOC_DISCARD, &plo->state))
return false;
+ if (plo->discard_disabled_count)
+ return false;
+
+ if (plo->maintenance_type != PLOOP_MNTN_OFF)
+ return false;
+
if (!list_is_singular(&plo->map.delta_list))
return false;
@@ -3591,13 +3632,17 @@ static int ploop_snapshot(struct ploop_device * plo, unsigned long arg,
if (IS_ERR(delta))
return PTR_ERR(delta);
- err = delta->ops->compose(delta, 1, &chunk);
+ err = disable_and_wait_discard(plo);
if (err)
goto out_destroy;
+ err = delta->ops->compose(delta, 1, &chunk);
+ if (err)
+ goto out_enable;
+
err = delta->ops->open(delta);
if (err)
- goto out_destroy;
+ goto out_enable;
err = KOBJECT_ADD(&delta->kobj, kobject_get(&plo->kobj),
"%d", delta->level);
@@ -3650,6 +3695,7 @@ static int ploop_snapshot(struct ploop_device * plo, unsigned long arg,
if (err)
goto out_close2;
+ enable_discard(plo);
return 0;
out_close2:
@@ -3657,6 +3703,8 @@ static int ploop_snapshot(struct ploop_device * plo, unsigned long arg,
out_close:
kobject_put(&plo->kobj);
delta->ops->stop(delta);
+out_enable:
+ enable_discard(plo);
out_destroy:
delta->ops->destroy(delta);
kobject_put(&delta->kobj);
@@ -4507,16 +4555,28 @@ static int ploop_grow(struct ploop_device *plo, struct block_device *bdev,
if (!delta->ops->prepare_grow)
return -EINVAL;
+ err = disable_and_wait_discard(plo);
+ if (err)
+ return -EINTR;
+
ploop_quiesce(plo);
err = delta->ops->prepare_grow(delta, &new_size, &reloc);
- if (err)
+ if (err) {
+ enable_discard(plo);
goto grow_failed;
+ }
plo->grow_new_size = new_size;
/* prepare_grow() succeeded, but more actions needed */
if (reloc) {
plo->maintenance_type = PLOOP_MNTN_GROW;
+ /*
+ * maintenance_type is changed, so now it prohibits
+ * discard bios. Below we may leave this function,
+ * and let's return discard counter back.
+ */
+ enable_discard(plo);
ploop_relax(plo);
for (; grow_stage < PLOOP_GROW_MAX; grow_stage++) {
ploop_relocate(plo, grow_stage);
@@ -4541,7 +4601,8 @@ static int ploop_grow(struct ploop_device *plo, struct block_device *bdev,
new_size = plo->grow_new_size;
clear_bit(PLOOP_S_NULLIFY, &plo->state);
plo->maintenance_type = PLOOP_MNTN_OFF;
- }
+ } else
+ enable_discard(plo);
/* Update bdev size and friends */
if (delta->ops->complete_grow) {
diff --git a/include/linux/ploop/ploop.h b/include/linux/ploop/ploop.h
index 688de1185d2b7..a22696e9c42e8 100644
--- a/include/linux/ploop/ploop.h
+++ b/include/linux/ploop/ploop.h
@@ -476,6 +476,7 @@ struct ploop_device
unsigned long locking_state; /* plo locked by userspace */
unsigned int fast_path_disabled_count;
+ unsigned int discard_disabled_count;
};
enum
More information about the Devel
mailing list