[1/2] ploop: add a standby mode

Submitted by Andrei Vagin on Feb. 27, 2018, 2:10 a.m.

Details

Message ID 1519697410-26352-1-git-send-email-avagin@openvz.org
State New
Series "Series without cover letter"
Headers show

Commit Message

Andrei Vagin Feb. 27, 2018, 2:10 a.m.
[This sender failed our fraud detection checks and may not be who they appear to be. Learn about spoofing at http://aka.ms/LearnAboutSpoofing]

This mode shows that a delta lease was stolen and it is impossible to
handle any requests.

We want to know about this situation from the iscsi target. When HA
decides that the current target is broken, it can initialize another
target with the same delta. In this case, the first target has to complete
all in-porgress commands and set the ASCQ_04H_ALUA_TG_PT_STANDBY bit in
their status.

In Linux, bio-s are always completed with EIO in error cases, so we need
another way how to determine this state. This patch addes a new block
queue flag QUEUE_FLAG_STANDBY.

https://pmc.acronis.com/browse/VSTOR-7879
Signed-off-by: Andrei Vagin <avagin@openvz.org>
---
 drivers/block/ploop/dev.c     | 11 +++++++++++
 drivers/block/ploop/io_kaio.c | 20 +++++++++++++++++++-
 include/linux/blkdev.h        |  3 +++
 3 files changed, 33 insertions(+), 1 deletion(-)

--
1.8.3.1

Patch hide | download patch | download mbox

diff --git a/drivers/block/ploop/dev.c b/drivers/block/ploop/dev.c
index 6c0b3c0..cf257a2 100644
--- a/drivers/block/ploop/dev.c
+++ b/drivers/block/ploop/dev.c
@@ -854,6 +854,11 @@  static void ploop_make_request(struct request_queue *q, struct bio *bio)
        part_stat_add(cpu, part, sectors[rw], bio_sectors(bio));
        part_stat_unlock();

+       if (blk_queue_standby(plo->queue)) {
+               BIO_ENDIO(q, bio, -EIO);
+               return;
+       }
+
        if (unlikely(bio->bi_size == 0)) {
                /* Is it possible? This makes sense if the request is
                 * marked as FLUSH, otherwise just warn and complete. */
@@ -3325,6 +3330,11 @@  static int ploop_replace_delta(struct ploop_device * plo, unsigned long arg)
        ploop_quiesce(plo);
        ploop_map_destroy(&plo->map);
        list_replace_init(&old_delta->list, &delta->list);
+
+       spin_lock_irq(plo->queue->queue_lock);
+       queue_flag_clear(QUEUE_FLAG_STANDBY, plo->queue);
+       spin_unlock_irq(plo->queue->queue_lock);
+
        ploop_relax(plo);

        old_delta->ops->stop(old_delta);
@@ -3988,6 +3998,7 @@  static int ploop_start(struct ploop_device * plo, struct block_device *bdev)

        blk_queue_max_discard_sectors(plo->queue, INT_MAX);
        queue_flag_set_unlocked(QUEUE_FLAG_DISCARD, plo->queue);
+       queue_flag_clear_unlocked(QUEUE_FLAG_STANDBY, plo->queue);

        set_capacity(plo->disk, plo->bd_size);
        bd_set_size(bdev, (loff_t)plo->bd_size << 9);
diff --git a/drivers/block/ploop/io_kaio.c b/drivers/block/ploop/io_kaio.c
index 42ba13b..c360f2d 100644
--- a/drivers/block/ploop/io_kaio.c
+++ b/drivers/block/ploop/io_kaio.c
@@ -118,15 +118,33 @@  static void kaio_rw_aio_complete(u64 data, long res)

        if (unlikely(res < 0)) {
                struct bio *b = preq->aux_bio;
+
                printk("kaio_rw_aio_complete: kaio failed with err=%ld "
                       "(rw=%s; state=%ld/0x%lx; clu=%d; iblk=%d; aux=%ld)\n",
                       res, (preq->req_rw & REQ_WRITE) ? "WRITE" : "READ",
                       preq->eng_state, preq->state, preq->req_cluster,
                       preq->iblock, b ? b->bi_sector : -1);
+
                bio_list_for_each(b, &preq->bl)
                        printk(" bio=%p: bi_sector=%ld bi_size=%d\n",
                               b, b->bi_sector, b->bi_size);
-               PLOOP_REQ_SET_ERROR(preq, res);
+
+               if (res == -EBUSY) { /* a delta lease was stolen */
+                       struct request_queue *q = preq->plo->queue;
+                       int prev;
+
+                       spin_lock_irq(q->queue_lock);
+                       prev = queue_flag_test_and_set(QUEUE_FLAG_STANDBY, q);
+                       spin_unlock_irq(q->queue_lock);
+
+                       if (!prev)
+                               printk("ploop%d was switched into "
+                                       "the standby mode\n", preq->plo->index);
+
+                       ploop_req_set_error(preq, res);
+               } else {
+                       PLOOP_REQ_SET_ERROR(preq, res);
+               }
        }

        kaio_complete_io_request(preq);
diff --git a/include/linux/blkdev.h b/include/linux/blkdev.h
index 24cb38b..7e92275 100644
--- a/include/linux/blkdev.h
+++ b/include/linux/blkdev.h
@@ -571,6 +571,8 @@  struct request_queue {
 #define QUEUE_FLAG_SG_GAPS     23      /* queue doesn't support SG gaps */
 #define QUEUE_FLAG_DAX         24      /* device supports DAX */

+#define QUEUE_FLAG_STANDBY     31      /* unable to handle read/write requests */
+
 #define QUEUE_FLAG_DEFAULT     ((1 << QUEUE_FLAG_IO_STAT) |            \
                                 (1 << QUEUE_FLAG_STACKABLE)    |       \
                                 (1 << QUEUE_FLAG_SAME_COMP)    |       \
@@ -661,6 +663,7 @@  static inline void queue_flag_clear(unsigned int flag, struct request_queue *q)
 #define blk_queue_secdiscard(q)        (blk_queue_discard(q) && \
        test_bit(QUEUE_FLAG_SECDISCARD, &(q)->queue_flags))
 #define blk_queue_dax(q)       test_bit(QUEUE_FLAG_DAX, &(q)->queue_flags)
+#define blk_queue_standby(q)   test_bit(QUEUE_FLAG_STANDBY, &(q)->queue_flags)

 #define blk_noretry_request(rq) \
        ((rq)->cmd_flags & (REQ_FAILFAST_DEV|REQ_FAILFAST_TRANSPORT| \