On 31.10.22 21:27, Denis V. Lunev wrote:
On 10/31/22 19:12, Alexander Atanasov wrote:
Initially in commit 80da9c2abac9 ("ploop: add a standby mode") a flag
on the block device's request queue was added to put the queue
into standby mode on EBUSY. Later on, the list with errors was extended
in commit e868f1e0b1a3 ("ploop: move to standby after -ENOTCONN too") and
in commit 4b1eb3f667eb ("ploop: kaio: Enter standby mode on EIO as well").

These were introduced to solve a problem on a specific device,
that will clear the standby flag at some point.
But the problem is that the clear counterpart was missing
for the rest of the devices, so once ploop gets one of the errors
it stops processing requests indefinitely.

When porting the feature restrict the standby mode flag to work only
on devices that handle it. To acheve this introduce a static key
to enable the flag handling only when key is enabled - checks are
at the start and at the end of every request and we want to avoid
performance impact from these checks.

On systems where we are in mixed mode, meaning we have both devices that
support the standby flag and devices that do not, a QUEUE_FLAG_STANDBY_EN
is introduced to indicate the standby support from the device.
Setting the QUEUE_FLAG_STANDBY_EN means the device promises to clear
QUEUE_FLAG_STANDBY flag when it recovers, so ploop can continue processing
requests.

The state of the flags is exported via /sys/block/*/queue/standby,
or at /sys/devices/virtual/block/*/queue depending on the device.
not supported - not enabled on the queue
on - queue is in standby mode, not processing requests
off - queue is processing requests

https://jira.sw.ru/browse/PSBM-142759
Signed-off-by: Alexander Atanasov <alexander.atana...@virtuozzo.com>
---
  block/blk-sysfs.c            | 10 ++++++++++
  drivers/md/dm-ploop-map.c    | 36 +++++++++++++++++++++++++++++++++++-
  drivers/md/dm-ploop-target.c | 12 +++++++++++-
  drivers/md/dm-ploop.h        |  1 +
  include/linux/blkdev.h       |  4 ++++
  kernel/ve/ve.c               |  9 +++++++++
  6 files changed, 70 insertions(+), 2 deletions(-)

Cc: Denis V. Lunev <d...@virtuozzo.com>
Cc: Kui Liu <kui....@acronis.com>
Cc: Alexey Kuznetsov <kuz...@acronis.com>

diff --git a/block/blk-sysfs.c b/block/blk-sysfs.c
index 4be6462c0008..c558c6c9a0ad 100644
--- a/block/blk-sysfs.c
+++ b/block/blk-sysfs.c
@@ -552,6 +552,14 @@ static ssize_t queue_dax_show(struct request_queue *q, char *page)
      return queue_var_show(blk_queue_dax(q), page);
  }
+static ssize_t queue_standby_show(struct request_queue *q, char *page)
+{
+    if (!blk_queue_standby_en(q))
+        return sprintf(page, "not supported\n");
+    return sprintf(page, "%s\n",
+        blk_queue_standby(q) ? "on" : "off");
+}
+
  #define QUEUE_RO_ENTRY(_prefix, _name)            \
  static struct queue_sysfs_entry _prefix##_entry = {    \
      .attr    = { .name = _name, .mode = 0444 },    \
@@ -606,6 +614,7 @@ QUEUE_RO_ENTRY(queue_dax, "dax");
  QUEUE_RW_ENTRY(queue_io_timeout, "io_timeout");
  QUEUE_RW_ENTRY(queue_wb_lat, "wbt_lat_usec");
  QUEUE_RO_ENTRY(queue_virt_boundary_mask, "virt_boundary_mask");
+QUEUE_RO_ENTRY(queue_standby, "standby");
  #ifdef CONFIG_BLK_DEV_THROTTLING_LOW
  QUEUE_RW_ENTRY(blk_throtl_sample_time, "throttle_sample_time");
@@ -667,6 +676,7 @@ static struct attribute *queue_attrs[] = {
      &blk_throtl_sample_time_entry.attr,
  #endif
      &queue_virt_boundary_mask_entry.attr,
+    &queue_standby_entry.attr,
      NULL,
  };
diff --git a/drivers/md/dm-ploop-map.c b/drivers/md/dm-ploop-map.c
index e8288e522e28..cb6f64814128 100644
--- a/drivers/md/dm-ploop-map.c
+++ b/drivers/md/dm-ploop-map.c
@@ -19,6 +19,7 @@
  #include <uapi/linux/falloc.h>
  #include "dm-ploop.h"
  #include "dm-rq.h"
+#include "dm-core.h"
  #define PREALLOC_SIZE (128ULL * 1024 * 1024)
@@ -28,6 +29,8 @@ static void ploop_prq_endio(struct pio *pio, void *prq_ptr,
  #define DM_MSG_PREFIX "ploop"
+extern struct static_key_false ploop_standby_check;
+
  static unsigned int ploop_pio_nr_segs(struct pio *pio)
  {
      struct bvec_iter bi = {
@@ -1163,6 +1166,26 @@ static void ploop_queue_resubmit(struct pio *pio)
      queue_work(ploop->wq, &ploop->worker);
  }
+static void ploop_check_standby_mode(struct ploop *ploop, long res)
+{
+    struct request_queue *q = ploop_blk_queue(ploop);
+    int prev;
+
+    if (!blk_queue_standby_en(q))
+        return;
+
+    /* move to standby if delta lease was stolen or mount is gone */
+    if (res != -EBUSY && res != -ENOTCONN && res != -EIO)
+        return;
+
+    spin_lock_irq(&q->queue_lock);
+    prev = blk_queue_flag_test_and_set(QUEUE_FLAG_STANDBY, q);
+    spin_unlock_irq(&q->queue_lock);
+
+    if (!prev)
+        pr_info("ploop: switch into standby mode\n");

some ploop identifier is needed here to determine device name

I'll add the device name here. dm-ploop logs without device name everywhere - i'll check that too.



+}
+
  static void ploop_data_rw_complete(struct pio *pio)
  {
      bool completed;
@@ -1175,6 +1198,8 @@ static void ploop_data_rw_complete(struct pio *pio)
              ploop_queue_resubmit(pio);
              return;
          }
+        if (static_branch_unlikely(&ploop_standby_check))
+            ploop_check_standby_mode(pio->ploop, pio->ret);
          pio->bi_status = errno_to_blk_status(pio->ret);
      }
@@ -1815,8 +1840,11 @@ void do_ploop_fsync_work(struct work_struct *ws)
      ret = vfs_fsync(file, 0);
      while ((pio = ploop_pio_list_pop(&flush_pios)) != NULL) {
-        if (unlikely(ret))
+        if (unlikely(ret)) {
              pio->bi_status = errno_to_blk_status(ret);
+            if (static_branch_unlikely(&ploop_standby_check))
+                ploop_check_standby_mode(ploop, ret);
+        }
          ploop_pio_endio(pio);
      }
  }
@@ -1869,6 +1897,12 @@ int ploop_clone_and_map(struct dm_target *ti, struct request *rq,
      struct ploop_rq *prq;
      struct pio *pio;
+
+    if (static_branch_unlikely(&ploop_standby_check)) {
+        if (blk_queue_standby(ploop_blk_queue(ploop)))
+            return DM_MAPIO_KILL;
+    }
+
      if (blk_rq_bytes(rq) && ploop_rq_valid(ploop, rq) < 0)
          return DM_MAPIO_KILL;
diff --git a/drivers/md/dm-ploop-target.c b/drivers/md/dm-ploop-target.c
index 4f7dc36eee0c..29c89dc8ba99 100644
--- a/drivers/md/dm-ploop-target.c
+++ b/drivers/md/dm-ploop-target.c
@@ -21,17 +21,19 @@
  #include <linux/uio.h>
  #include <linux/error-injection.h>
  #include "dm-ploop.h"
+#include "dm-core.h"
  #define DM_MSG_PREFIX "ploop"
  bool ignore_signature_disk_in_use = false; /* For development purposes */
  module_param(ignore_signature_disk_in_use, bool, 0444);
  MODULE_PARM_DESC(ignore_signature_disk_in_use,
-                "Does not check for SIGNATURE_DISK_IN_USE");
+        "Does not check for SIGNATURE_DISK_IN_USE");
please do not touch unrelated places

ok


  static struct kmem_cache *prq_cache;
  static struct kmem_cache *pio_cache;
  struct kmem_cache *cow_cache;
+extern struct static_key_false ploop_standby_check;
  static void ploop_aio_do_completion(struct pio *pio)
  {
@@ -406,6 +408,14 @@ static int ploop_ctr(struct dm_target *ti, unsigned int argc, char **argv)
      ti->private = ploop;
      ploop->ti = ti;
+    if (blk_queue_standby_en(ploop_blk_queue(ploop))) {
+        blk_queue_flag_clear(QUEUE_FLAG_STANDBY, ploop_blk_queue(ploop));
+        if (static_branch_unlikely(&ploop_standby_check)) {
this point should NOT be reached. If it is reached - SCST has violated the protocol at my opinion

If any other device wants to user the flag and it sets it before _ctr it will catch it and enable the key. I can change it to a WARN_ON if _en is set but key is not.

[snip]

--
Regards,
Alexander Atanasov

_______________________________________________
Devel mailing list
Devel@openvz.org
https://lists.openvz.org/mailman/listinfo/devel

Reply via email to