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

Submitted by Maxim Patlasov on Oct. 30, 2016, 5:37 p.m.

Details

Message ID 147784906631.3102.1752700186327682181.stgit@maxim-thinkpad
State New
Series "ploop: push_backup: avoid preq->state corruption"
Headers show

Commit Message

Maxim Patlasov Oct. 30, 2016, 5:37 p.m.
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 a8720db..8bfd96a 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;
@@ -2201,7 +2202,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 8f19310..975d2be 100644
--- a/drivers/block/ploop/push_backup.c
+++ b/drivers/block/ploop/push_backup.c
@@ -924,7 +924,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 b8c480a..c14da7b 100644
--- a/include/linux/ploop/ploop.h
+++ b/include/linux/ploop/ploop.h
@@ -567,8 +567,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;