[Devel,RHEL7,COMMIT] ploop: push_backup: avoid preq->state corruption

Submitted by Konstantin Khorenko on Nov. 25, 2016, 2:46 p.m.

Details

Message ID 201611251446.uAPEk4jV022599@finist_cl7.x64_64.work.ct
State New
Series "ploop: push_backup: avoid preq->state corruption"
Headers show

Commit Message

Konstantin Khorenko Nov. 25, 2016, 2:46 p.m.
The commit is pushed to "branch-rh7-3.10.0-327.36.1.vz7.20.x-ovz" and will appear at https://src.openvz.org/scm/ovz/vzkernel.git
after rh7-3.10.0-327.36.1.vz7.20.3
------>
commit da4499838c05973f78e010961f547b2418bb7db6
Author: Maxim Patlasov <mpatlasov@virtuozzo.com>
Date:   Fri Nov 25 18:46:04 2016 +0400

    ploop: push_backup: avoid preq->state corruption
    
    ploop-state-machine does not expect someone else changing preq->state.
    Hence, __set_bit(lockout_bit, &preq->state) called from ploop_thread()
    races with __set_bit(PLOOP_REQ_PUSH_BACKUP, &preq->state) called from
    ioctl(PLOOP_IOC_PUSH_BACKUP_IO) handler.
    
    The only place where push_backup engine modifies preq->state is that
    __set_bit(PLOOP_REQ_PUSH_BACKUP, &preq->state) from ploop_pb_process_extent().
    So the patch simply moves this bit from preq->state to preq->ppb_state
    ensuring that only race-safe set_bit() changes it.
    
    Signed-off-by: Maxim Patlasov <mpatlasov@virtuozzo.com>
---
 drivers/block/ploop/dev.c         | 3 ++-
 drivers/block/ploop/push_backup.c | 2 +-
 include/linux/ploop/ploop.h       | 9 +++++++--
 3 files changed, 10 insertions(+), 4 deletions(-)

Patch hide | download patch | download mbox

diff --git a/drivers/block/ploop/dev.c b/drivers/block/ploop/dev.c
index 26017eb..4600bfe 100644
--- a/drivers/block/ploop/dev.c
+++ b/drivers/block/ploop/dev.c
@@ -521,6 +521,7 @@  ploop_bio_queue(struct ploop_device * plo, struct bio * bio,
 	preq->req_rw = bio->bi_rw;
 	preq->eng_state = PLOOP_E_ENTRY;
 	preq->state = 0;
+	preq->ppb_state = 0;
 	preq->error = 0;
 	preq->tstamp = jiffies;
 	preq->iblock = 0;
@@ -2266,7 +2267,7 @@  restart:
 			return;
 		}
 	} else if (test_bit(PLOOP_REQ_PB_LOCKOUT, &preq->state) &&
-		   test_and_clear_bit(PLOOP_REQ_PUSH_BACKUP, &preq->state)) {
+		   test_and_clear_bit(PLOOP_REQ_PUSH_BACKUP, &preq->ppb_state)) {
 		/*
 		 * preq OUT: out-of-band push_backup processing by
 		 * userspace done; preq was re-scheduled
diff --git a/drivers/block/ploop/push_backup.c b/drivers/block/ploop/push_backup.c
index f825575..5afe643 100644
--- a/drivers/block/ploop/push_backup.c
+++ b/drivers/block/ploop/push_backup.c
@@ -926,7 +926,7 @@  static void ploop_pb_process_extent(struct pb_set *pbs, cluster_t clu,
 	while (preq) {
 		struct rb_node *n;
 
-		__set_bit(PLOOP_REQ_PUSH_BACKUP, &preq->state);
+		set_bit(PLOOP_REQ_PUSH_BACKUP, &preq->ppb_state);
 		list_add(&preq->list, ready_list);
 
 		if (n_found)
diff --git a/include/linux/ploop/ploop.h b/include/linux/ploop/ploop.h
index 8abc6f9..280bbab 100644
--- a/include/linux/ploop/ploop.h
+++ b/include/linux/ploop/ploop.h
@@ -570,8 +570,13 @@  struct ploop_request
 	iblock_t		iblock;
 
 	/* relocation info */
-	iblock_t		src_iblock;
-	iblock_t		dst_iblock;
+	union {
+		struct {
+			iblock_t      src_iblock;
+			iblock_t      dst_iblock;
+		};
+		unsigned long	      ppb_state;
+	};
 	cluster_t		dst_cluster;
 	struct rb_node		reloc_link;