The counter represents the number of ploop requests that
potentially can be blocked due to push_backup: let's call
them "blockable" requersts. In the other words they are
those who is going to be dependent on userspace backup tool.

We claim a preq as "blockable" if, at the time of converting
incoming bio to the preq, we observe corresponding bit in
pbd->ppb_map set, and corresponding bit in pbd->reported_map
is clear.

In case of in-flight conversion (ploop_make_request calling
process_bio_queue) the decision is posponed until ploop_thread
process preq by ploop_req_state_process(). This is done
intentionally, to avoid locking scheme complication.

The counter will be used by next patch of this patch-set.

https://jira.sw.ru/browse/PSBM-49454

Signed-off-by: Maxim Patlasov <mpatla...@virtuozzo.com>
---
 drivers/block/ploop/dev.c         |   36 ++++++++++++++++++++++++++++++------
 drivers/block/ploop/push_backup.c |   22 ++++++++++++++++++++++
 drivers/block/ploop/push_backup.h |    1 +
 drivers/block/ploop/sysfs.c       |    6 ++++++
 include/linux/ploop/ploop.h       |    2 ++
 5 files changed, 61 insertions(+), 6 deletions(-)

diff --git a/drivers/block/ploop/dev.c b/drivers/block/ploop/dev.c
index cc33b2d..6795b95 100644
--- a/drivers/block/ploop/dev.c
+++ b/drivers/block/ploop/dev.c
@@ -227,6 +227,20 @@ static inline void preq_unlink(struct ploop_request * preq,
        list_add(&preq->list, drop_list);
 }
 
+static void ploop_set_blockable(struct ploop_device *plo,
+                               struct ploop_request *preq)
+{
+       if (!test_and_set_bit(PLOOP_REQ_BLOCKABLE, &preq->state))
+               plo->blockable_reqs++;
+}
+
+static void ploop_test_and_clear_blockable(struct ploop_device *plo,
+                                          struct ploop_request *preq)
+{
+       if (test_and_clear_bit(PLOOP_REQ_BLOCKABLE, &preq->state))
+               plo->blockable_reqs--;
+}
+
 /* always called with plo->lock released */
 void ploop_preq_drop(struct ploop_device * plo, struct list_head *drop_list,
                      int keep_locked)
@@ -242,6 +256,7 @@ void ploop_preq_drop(struct ploop_device * plo, struct 
list_head *drop_list,
                }
 
                BUG_ON (test_bit(PLOOP_REQ_ZERO, &preq->state));
+               ploop_test_and_clear_blockable(plo, preq);
                drop_qlen++;
        }
 
@@ -489,7 +504,7 @@ insert_entry_tree(struct ploop_device * plo, struct 
ploop_request * preq0,
 
 static void
 ploop_bio_queue(struct ploop_device * plo, struct bio * bio,
-               struct list_head *drop_list)
+               struct list_head *drop_list, int account_blockable)
 {
        struct ploop_request * preq;
 
@@ -511,6 +526,10 @@ ploop_bio_queue(struct ploop_device * plo, struct bio * 
bio,
        preq->iblock = 0;
        preq->prealloc_size = 0;
 
+       if (account_blockable && (bio->bi_rw & REQ_WRITE) && bio->bi_size &&
+           ploop_pb_check_and_clear_bit(plo->pbd, preq->req_cluster))
+               ploop_set_blockable(plo, preq);
+
        if (unlikely(bio->bi_rw & REQ_DISCARD)) {
                int clu_size = 1 << plo->cluster_log;
                int i = (clu_size - 1) & bio->bi_sector;
@@ -734,7 +753,9 @@ preallocate_bio(struct bio * orig_bio, struct ploop_device 
* plo)
        return nbio;
 }
 
-static void process_bio_queue(struct ploop_device * plo, struct list_head 
*drop_list)
+static void process_bio_queue(struct ploop_device * plo,
+                             struct list_head *drop_list,
+                             int account_blockable)
 {
        while (plo->bio_head && !list_empty(&plo->free_list)) {
                struct bio *tmp = plo->bio_head;
@@ -744,7 +765,7 @@ static void process_bio_queue(struct ploop_device * plo, 
struct list_head *drop_
                if (!plo->bio_head)
                        plo->bio_tail = NULL;
 
-               ploop_bio_queue(plo, tmp, drop_list);
+               ploop_bio_queue(plo, tmp, drop_list, account_blockable);
        }
 }
 
@@ -796,7 +817,7 @@ process_discard_bio_queue(struct ploop_device * plo, struct 
list_head *drop_list
                /* If PLOOP_S_DISCARD isn't set, ploop_bio_queue
                 * will complete it with a proper error.
                 */
-               ploop_bio_queue(plo, tmp, drop_list);
+               ploop_bio_queue(plo, tmp, drop_list, 0);
        }
 }
 
@@ -1001,7 +1022,7 @@ queue:
        ploop_congest(plo);
 
        /* second chance to merge requests */
-       process_bio_queue(plo, &drop_list);
+       process_bio_queue(plo, &drop_list, 0);
 
 queued:
        /* If main thread is waiting for requests, wake it up.
@@ -1371,6 +1392,7 @@ static void ploop_complete_request(struct ploop_request * 
preq)
 
        del_lockout(preq);
        del_pb_lockout(preq); /* preq may die via ploop_fail_immediate() */
+       ploop_test_and_clear_blockable(plo, preq);
 
        if (!list_empty(&preq->delay_list))
                list_splice_init(&preq->delay_list, plo->ready_queue.prev);
@@ -2139,6 +2161,7 @@ restart:
                } else {
                        /* needn't lock because only ploop_thread accesses */
                        ploop_add_pb_lockout(preq);
+                       ploop_set_blockable(plo, preq);
                        /*
                         * preq IN: preq is in ppb_pending tree waiting for
                         * out-of-band push_backup processing by userspace ...
@@ -2152,6 +2175,7 @@ restart:
                 * userspace done; preq was re-scheduled
                 */
                ploop_pb_clear_bit(plo->pbd, preq->req_cluster);
+               ploop_test_and_clear_blockable(plo, preq);
 
                del_pb_lockout(preq);
                spin_lock_irq(&plo->lock);
@@ -2855,7 +2879,7 @@ static int ploop_thread(void * data)
        again:
                BUG_ON (!list_empty(&drop_list));
 
-               process_bio_queue(plo, &drop_list);
+               process_bio_queue(plo, &drop_list, 1);
                process_discard_bio_queue(plo, &drop_list);
 
                if (!list_empty(&drop_list)) {
diff --git a/drivers/block/ploop/push_backup.c 
b/drivers/block/ploop/push_backup.c
index 4e2404c..c58aadf 100644
--- a/drivers/block/ploop/push_backup.c
+++ b/drivers/block/ploop/push_backup.c
@@ -657,6 +657,28 @@ int ploop_pb_preq_add_pending(struct ploop_pushbackup_desc 
*pbd,
        return 0;
 }
 
+bool ploop_pb_check_and_clear_bit(struct ploop_pushbackup_desc *pbd,
+                                 cluster_t clu)
+{
+       if (!pbd)
+               return false;
+
+       if (!check_bit_in_map(pbd->ppb_map, pbd->ppb_block_max, clu))
+               return false;
+
+       spin_lock(&pbd->ppb_lock);
+
+       if (pbd->ppb_state != PLOOP_PB_ALIVE ||
+           check_bit_in_map(pbd->reported_map, pbd->ppb_block_max, clu)) {
+               spin_unlock(&pbd->ppb_lock);
+               ploop_pb_clear_bit(pbd, clu);
+               return false;
+       }
+
+       spin_unlock(&pbd->ppb_lock);
+       return true;
+}
+
 /* Always serialized by plo->ctl_mutex */
 unsigned long ploop_pb_stop(struct ploop_pushbackup_desc *pbd, bool do_merge)
 {
diff --git a/drivers/block/ploop/push_backup.h 
b/drivers/block/ploop/push_backup.h
index 5333537..0d479e0 100644
--- a/drivers/block/ploop/push_backup.h
+++ b/drivers/block/ploop/push_backup.h
@@ -24,6 +24,7 @@ void ploop_pb_put_reported(struct ploop_pushbackup_desc *pbd,
 
 void ploop_pb_clear_bit(struct ploop_pushbackup_desc *pbd, cluster_t clu);
 bool ploop_pb_check_bit(struct ploop_pushbackup_desc *pbd, cluster_t clu);
+bool ploop_pb_check_and_clear_bit(struct ploop_pushbackup_desc *pbd, cluster_t 
clu);
 
 int ploop_pb_preq_add_pending(struct ploop_pushbackup_desc *pbd,
                               struct ploop_request *preq);
diff --git a/drivers/block/ploop/sysfs.c b/drivers/block/ploop/sysfs.c
index c062c1e..2160fb31 100644
--- a/drivers/block/ploop/sysfs.c
+++ b/drivers/block/ploop/sysfs.c
@@ -435,6 +435,11 @@ static u32 show_free_qmax(struct ploop_device * plo)
        return plo->free_qmax;
 }
 
+static u32 show_blockable_reqs(struct ploop_device * plo)
+{
+       return plo->blockable_reqs;
+}
+
 #define _TUNE_U32(_name)                               \
 static u32 show_##_name(struct ploop_device * plo)     \
 {                                                      \
@@ -519,6 +524,7 @@ static struct attribute *state_attributes[] = {
        _A(open_count),
        _A(free_reqs),
        _A(free_qmax),
+       _A(blockable_reqs),
        NULL
 };
 
diff --git a/include/linux/ploop/ploop.h b/include/linux/ploop/ploop.h
index 87a530e..43bba66 100644
--- a/include/linux/ploop/ploop.h
+++ b/include/linux/ploop/ploop.h
@@ -366,6 +366,7 @@ struct ploop_device
        int                     read_sync_reqs;
        int                     free_qlen; /* len of free_list */
        int                     free_qmax; /* max len of free_list */
+       int                     blockable_reqs; /* depends on userspace tool */
 
        struct bio              *bio_head;
        struct bio              *bio_tail;
@@ -484,6 +485,7 @@ enum
        PLOOP_REQ_PUSH_BACKUP, /* preq was ACKed by userspace push_backup */
        PLOOP_REQ_FSYNC_DONE,  /* fsync_thread() performed f_op->fsync() */
        PLOOP_REQ_ISSUE_FLUSH, /* preq needs ->issue_flush before completing */
+       PLOOP_REQ_BLOCKABLE,  /* preq was accounted in plo->blockable_reqs */
 };
 
 #define PLOOP_REQ_MERGE_FL (1 << PLOOP_REQ_MERGE)

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

Reply via email to