[RHEL7,COMMIT] ploop: add a standby mode

Submitted by Konstantin Khorenko on March 1, 2018, 8:07 a.m.

Details

Message ID 201803010807.w2187Y30007427@finist_ce7.work
State New
Series "ploop: add a standby mode"
Headers show

Commit Message

Konstantin Khorenko March 1, 2018, 8:07 a.m.
The commit is pushed to "branch-rh7-3.10.0-693.17.1.vz7.45.x-ovz" and will appear at https://src.openvz.org/scm/ovz/vzkernel.git
after rh7-3.10.0-693.17.1.vz7.45.6
------>
commit 6df39ebe7c8648bc176a87129668603aef7386ed
Author: Andrei Vagin <avagin@openvz.org>
Date:   Thu Mar 1 11:07:34 2018 +0300

    ploop: add a standby mode
    
    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(-)

Patch hide | download patch | download mbox

diff --git a/drivers/block/ploop/dev.c b/drivers/block/ploop/dev.c
index 82d986922b4b..533ddc965af2 100644
--- a/drivers/block/ploop/dev.c
+++ b/drivers/block/ploop/dev.c
@@ -858,6 +858,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. */
@@ -3329,6 +3334,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);
@@ -3992,6 +4002,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 54604065c64e..c7312c54595e 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 24cb38b872fb..7e9227543735 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| \