The issue is old, it was found and fixed in user space,
but we forgot to update kernel as well.

Signed-off-by: Alexey Kuznetsov <kuz...@virtuozzo.com>
---
 fs/fuse/kio/pcs/pcs_cluster.c      |  1 +
 fs/fuse/kio/pcs/pcs_cluster_core.c | 17 +++++++++++++++++
 fs/fuse/kio/pcs/pcs_cs.c           | 18 ++++++++++++++----
 fs/fuse/kio/pcs/pcs_map.c          | 15 ++++++++++++---
 fs/fuse/kio/pcs/pcs_req.h          |  4 +++-
 5 files changed, 47 insertions(+), 8 deletions(-)

diff --git a/fs/fuse/kio/pcs/pcs_cluster.c b/fs/fuse/kio/pcs/pcs_cluster.c
index c64668a..c87313b 100644
--- a/fs/fuse/kio/pcs/pcs_cluster.c
+++ b/fs/fuse/kio/pcs/pcs_cluster.c
@@ -47,6 +47,7 @@ void pcs_sreq_complete(struct pcs_int_request *sreq)
                         */
                        if (ireq_check_redo(sreq)) {
                                ireq_retry_inc(ireq);
+                               sreq->flags &= ~IREQ_F_REQUEUED;
                                if (sreq->type != PCS_IREQ_CUSTOM) {
                                        map_notify_soft_error(sreq);
 
diff --git a/fs/fuse/kio/pcs/pcs_cluster_core.c 
b/fs/fuse/kio/pcs/pcs_cluster_core.c
index 86fe185..10d61f2 100644
--- a/fs/fuse/kio/pcs/pcs_cluster_core.c
+++ b/fs/fuse/kio/pcs/pcs_cluster_core.c
@@ -250,3 +250,20 @@ void pcs_cc_requeue(struct pcs_cluster_core *cc, struct 
list_head *q)
        if (was_idle)
                queue_work(cc->wq, &cc->main_job);
 }
+
+void pcs_cc_requeue_head(struct pcs_cluster_core *cc, struct list_head *q)
+{
+       unsigned long flags;
+       int was_idle = 0;
+
+       if (list_empty(q))
+               return;
+
+       spin_lock_irqsave(&cc->lock, flags);
+       was_idle = list_empty(&cc->work_queue);
+       list_splice_init(q, &cc->work_queue);
+       spin_unlock_irqrestore(&cc->lock, flags);
+
+       if (was_idle)
+               queue_work(cc->wq, &cc->main_job);
+}
diff --git a/fs/fuse/kio/pcs/pcs_cs.c b/fs/fuse/kio/pcs/pcs_cs.c
index b2ad511..0707575 100644
--- a/fs/fuse/kio/pcs/pcs_cs.c
+++ b/fs/fuse/kio/pcs/pcs_cs.c
@@ -314,7 +314,7 @@ void cs_log_io_times(struct pcs_int_request * ireq, struct 
pcs_msg * resp, unsig
                        th->ino = ireq->dentry->fileinfo.attr.id;
                        th->type = h->hdr.type;
                        th->cses = 1;
-                       th->__pad = 0;
+                       th->__pad = ((!!(ireq->flags & IREQ_F_REQUEUED)) << 7) 
| smp_processor_id();
                        th->chid = (unsigned int)h->uid;
 
                        ch->csid = resp->rpc->peer_id.val;
@@ -1549,13 +1549,23 @@ int pcs_cs_cong_enqueue_cond(struct pcs_int_request 
*ireq, struct pcs_cs *cs)
        int queued = 0;
 
        spin_lock(&cs->lock);
-       if (cs->in_flight >= cs->eff_cwnd) {
-               list_add_tail(&ireq->list, &cs->cong_queue);
+       if (cs->in_flight >= cs->eff_cwnd ||
+           (cs->cong_queue_len && !(ireq->flags & IREQ_F_REQUEUED))) {
+               queued = 1;
+               if (!list_empty(&cs->active_list)) {
+                       list_add_tail(&ireq->list, &cs->active_list);
+                       queued = 2;
+               } else
+                       list_add_tail(&ireq->list, &cs->cong_queue);
                cs->cong_queue_len++;
                if (!ireq->qdepth)
                        ireq->qdepth = cs->cong_queue_len;
-               queued = 1;
        }
+       if (queued && ireq->type == PCS_IREQ_IOCHUNK)
+               FUSE_KDTRACE(ireq->cc->fc, "queued%d {%p} cpu%u %d %u/%u " 
DENTRY_FMT " %llu+%llu",
+                            queued, ireq, smp_processor_id(), 
cs->cong_queue_len,
+                            cs->in_flight, cs->eff_cwnd, 
DENTRY_ARGS(ireq->dentry),
+                            ireq->iochunk.chunk + ireq->iochunk.offset, 
ireq->iochunk.size);
        spin_unlock(&cs->lock);
        return queued;
 }
diff --git a/fs/fuse/kio/pcs/pcs_map.c b/fs/fuse/kio/pcs/pcs_map.c
index 221e9f8..5d1dd5a 100644
--- a/fs/fuse/kio/pcs/pcs_map.c
+++ b/fs/fuse/kio/pcs/pcs_map.c
@@ -1235,7 +1235,7 @@ void pcs_map_complete(struct pcs_map_entry *m, struct 
pcs_ioc_getmap *omap)
        spin_unlock(&m->lock);
 
        /* Success, resubmit waiting requests */
-       pcs_cc_requeue(cc_from_map(m), &queue);
+       pcs_cc_requeue_head(cc_from_map(m), &queue);
        BUG_ON(!list_empty(&queue));
        pcs_map_put(m);
 
@@ -1575,7 +1575,15 @@ static void pcs_cs_wakeup(struct pcs_cs * cs)
                        sreq = parent;
                }
 
+               sreq->flags |= IREQ_F_REQUEUED;
+
                if (sreq->type != PCS_IREQ_FLUSH) {
+                       FUSE_KDTRACE(sreq->cc->fc,
+                                    "wakeup {%p} cpu%u %d %u/%u " DENTRY_FMT " 
%llu+%llu",
+                                    sreq, smp_processor_id(), 
cs->cong_queue_len,
+                                    cs->in_flight, cs->eff_cwnd, 
DENTRY_ARGS(sreq->dentry),
+                                    sreq->iochunk.chunk + sreq->iochunk.offset,
+                                    sreq->iochunk.size);
                        map = pcs_find_get_map(sreq->dentry, 
sreq->iochunk.chunk +
                                                   ((sreq->flags & 
IREQ_F_MAPPED) ? 0 : sreq->iochunk.offset));
                        if (map) {
@@ -2057,7 +2065,7 @@ static int pcs_cslist_submit_read(struct pcs_int_request 
*ireq, struct pcs_cs_li
        allot = cs->eff_cwnd - cs->in_flight;
        spin_unlock(&cs->lock);
 
-       if (allot < 0) {
+       if (allot < 0 || cs->cong_queue_len) {
                if (pcs_cs_cong_enqueue_cond(ireq, cs))
                        return 0;
        }
@@ -2109,7 +2117,7 @@ static int pcs_cslist_submit_read(struct pcs_int_request 
*ireq, struct pcs_cs_li
                if (sreq == ireq)
                        return 0;
 
-               if (allot < 0) {
+               if (allot < 0 || !list_empty(&cs->cong_queue)) {
                        if (pcs_cs_cong_enqueue_cond(ireq, cs))
                                return 0;
                }
@@ -3128,6 +3136,7 @@ static void pcs_flushreq_complete(struct pcs_int_request 
* sreq)
                        map_notify_error(m, sreq, &ioh->map_version, 
sreq->flushreq.csl);
                        pcs_deaccount_ireq(sreq, &sreq->error);
                        pcs_clear_error(&sreq->error);
+                       sreq->flags &= ~IREQ_F_REQUEUED;
 
                        if (!(sreq->flags & IREQ_F_ONCE)) {
                                sreq->flags |= IREQ_F_ONCE;
diff --git a/fs/fuse/kio/pcs/pcs_req.h b/fs/fuse/kio/pcs/pcs_req.h
index e43d28e..1503e59 100644
--- a/fs/fuse/kio/pcs/pcs_req.h
+++ b/fs/fuse/kio/pcs/pcs_req.h
@@ -130,7 +130,8 @@ struct pcs_int_request
 #define IREQ_F_CRYPT           0x2000
 #define IREQ_F_ACCELERROR      0x4000
 #define IREQ_F_NOACCT          0x8000
-#define IREQ_F_FANOUT         0x10000
+#define IREQ_F_FANOUT          0x10000
+#define IREQ_F_REQUEUED                0x20000
 
        atomic_t                iocount;
 
@@ -350,6 +351,7 @@ static inline struct pcs_cluster_core *cc_from_krpc(struct 
pcs_krpc *krpc)
 
 void pcs_cc_submit(struct pcs_cluster_core *cc, struct pcs_int_request* ireq);
 void pcs_cc_requeue(struct pcs_cluster_core *cc, struct list_head * q);
+void pcs_cc_requeue_head(struct pcs_cluster_core *cc, struct list_head *q);
 void pcs_cc_update_storage_versions(struct pcs_cluster_core *cc, int version);
 /* FROM pcs_cluster.h */
 static inline void pcs_sreq_attach(struct pcs_int_request * sreq, struct 
pcs_int_request * parent)
-- 
1.8.3.1

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

Reply via email to