The commit is pushed to "temp1" and will appear at 
https://src.openvz.org/scm/ovz/vzkernel.git
after rh7-3.10.0-327.3.1.el7
------>
commit d250d14fda418b7c2cf00005cea2ded9000342d5
Author: Vladimir Davydov <vdavy...@virtuozzo.com>
Date:   Fri Dec 25 13:48:40 2015 +0400

    ms/xfs: convert dquot cache lru to list_lru
    
    Patch series description:
    
    https://jira.sw.ru/browse/PSBM-42319
    
    Andrew Morton (1):
      xfs-convert-dquot-cache-lru-to-list_lru-fix
    
    Dave Chinner (2):
      xfs: convert dquot cache lru to list_lru
      xfs: fix dquot isolation hang
    
    Vladimir Davydov (3):
      xfs_qm: lost hunk from "ms/list_lru: dynamically adjust node arrays"
      xfs_qm: lost hunk from "ms/list_lru: introduce
        list_lru_shrink_{count,walk}"
      xfs_qm: lost hunk from "ms/list_lru: add helpers to isolate items"
    
    ================================
    This patch description:
    
    From: Dave Chinner <dchin...@redhat.com>
    
    Convert the XFS dquot lru to use the list_lru construct and convert the
    shrinker to being node aware.
    
    [glom...@openvz.org: edited for conflicts + warning fixes]
    Signed-off-by: Dave Chinner <dchin...@redhat.com>
    Signed-off-by: Glauber Costa <glom...@openvz.org>
    Cc: "Theodore Ts'o" <ty...@mit.edu>
    Cc: Adrian Hunter <adrian.hun...@intel.com>
    Cc: Al Viro <v...@zeniv.linux.org.uk>
    Cc: Artem Bityutskiy <artem.bityuts...@linux.intel.com>
    Cc: Arve Hjønnevåg <a...@android.com>
    Cc: Carlos Maiolino <cmaiol...@redhat.com>
    Cc: Christoph Hellwig <h...@lst.de>
    Cc: Chuck Lever <chuck.le...@oracle.com>
    Cc: Daniel Vetter <daniel.vet...@ffwll.ch>
    Cc: David Rientjes <rient...@google.com>
    Cc: Gleb Natapov <g...@redhat.com>
    Cc: Greg Thelen <gthe...@google.com>
    Cc: J. Bruce Fields <bfie...@redhat.com>
    Cc: Jan Kara <j...@suse.cz>
    Cc: Jerome Glisse <jgli...@redhat.com>
    Cc: John Stultz <john.stu...@linaro.org>
    Cc: KAMEZAWA Hiroyuki <kamezawa.hir...@jp.fujitsu.com>
    Cc: Kent Overstreet <koverstr...@google.com>
    Cc: Kirill A. Shutemov <kirill.shute...@linux.intel.com>
    Cc: Marcelo Tosatti <mtosa...@redhat.com>
    Cc: Mel Gorman <mgor...@suse.de>
    Cc: Steven Whitehouse <swhit...@redhat.com>
    Cc: Thomas Hellstrom <thellst...@vmware.com>
    Cc: Trond Myklebust <trond.mykleb...@netapp.com>
    Signed-off-by: Andrew Morton <a...@linux-foundation.org>
    
    Signed-off-by: Al Viro <v...@zeniv.linux.org.uk>
    (cherry picked from commit cd56a39a59868911bbf8832725630c1cf43a7b09)
    Signed-off-by: Vladimir Davydov <vdavy...@virtuozzo.com>
    
    Conflicts:
        fs/xfs/xfs_dquot.c
        fs/xfs/xfs_qm.c
---
 fs/xfs/xfs_dquot.c |   7 +-
 fs/xfs/xfs_qm.c    | 276 +++++++++++++++++++++++++++--------------------------
 fs/xfs/xfs_qm.h    |   4 +-
 3 files changed, 144 insertions(+), 143 deletions(-)

diff --git a/fs/xfs/xfs_dquot.c b/fs/xfs/xfs_dquot.c
index a0f4af0..b4f2af6 100644
--- a/fs/xfs/xfs_dquot.c
+++ b/fs/xfs/xfs_dquot.c
@@ -849,13 +849,8 @@ xfs_qm_dqput(
                struct xfs_quotainfo    *qi = dqp->q_mount->m_quotainfo;
                trace_xfs_dqput_free(dqp);
 
-               mutex_lock(&qi->qi_lru_lock);
-               if (list_empty(&dqp->q_lru)) {
-                       list_add_tail(&dqp->q_lru, &qi->qi_lru_list);
-                       qi->qi_lru_count++;
+               if (list_lru_add(&qi->qi_lru, &dqp->q_lru))
                        XFS_STATS_INC(xs_qm_dquot_unused);
-               }
-               mutex_unlock(&qi->qi_lru_lock);
 
        }
        xfs_dqunlock(dqp);
diff --git a/fs/xfs/xfs_qm.c b/fs/xfs/xfs_qm.c
index ed7310d..e831704 100644
--- a/fs/xfs/xfs_qm.c
+++ b/fs/xfs/xfs_qm.c
@@ -46,8 +46,9 @@
  */
 STATIC int     xfs_qm_init_quotainos(xfs_mount_t *);
 STATIC int     xfs_qm_init_quotainfo(xfs_mount_t *);
-STATIC int     xfs_qm_shake(struct shrinker *, struct shrink_control *);
 
+
+STATIC void    xfs_qm_dqfree_one(struct xfs_dquot *dqp);
 /*
  * We use the batch lookup interface to iterate over the dquots as it
  * currently is the only interface into the radix tree code that allows
@@ -181,12 +182,9 @@ xfs_qm_dqpurge(
         * We move dquots to the freelist as soon as their reference count
         * hits zero, so it really should be on the freelist here.
         */
-       mutex_lock(&qi->qi_lru_lock);
        ASSERT(!list_empty(&dqp->q_lru));
-       list_del_init(&dqp->q_lru);
-       qi->qi_lru_count--;
+       list_lru_del(&qi->qi_lru, &dqp->q_lru);
        XFS_STATS_DEC(xs_qm_dquot_unused);
-       mutex_unlock(&qi->qi_lru_lock);
 
        xfs_qm_dqdestroy(dqp);
        return 0;
@@ -424,6 +422,141 @@ xfs_qm_dqdetach(
        }
 }
 
+struct xfs_qm_isolate {
+       struct list_head        buffers;
+       struct list_head        dispose;
+};
+
+static enum lru_status
+xfs_qm_dquot_isolate(
+       struct list_head        *item,
+       spinlock_t              *lru_lock,
+       void                    *arg)
+{
+       struct xfs_dquot        *dqp = container_of(item,
+                                               struct xfs_dquot, q_lru);
+       struct xfs_qm_isolate   *isol = arg;
+
+       if (!xfs_dqlock_nowait(dqp))
+               goto out_miss_busy;
+
+       /*
+        * This dquot has acquired a reference in the meantime remove it from
+        * the freelist and try again.
+        */
+       if (dqp->q_nrefs) {
+               xfs_dqunlock(dqp);
+               XFS_STATS_INC(xs_qm_dqwants);
+
+               trace_xfs_dqreclaim_want(dqp);
+               list_del_init(&dqp->q_lru);
+               XFS_STATS_DEC(xs_qm_dquot_unused);
+               return 0;
+       }
+
+       /*
+        * If the dquot is dirty, flush it. If it's already being flushed, just
+        * skip it so there is time for the IO to complete before we try to
+        * reclaim it again on the next LRU pass.
+        */
+       if (!xfs_dqflock_nowait(dqp)) {
+               xfs_dqunlock(dqp);
+               goto out_miss_busy;
+       }
+
+       if (XFS_DQ_IS_DIRTY(dqp)) {
+               struct xfs_buf  *bp = NULL;
+               int             error;
+
+               trace_xfs_dqreclaim_dirty(dqp);
+
+               /* we have to drop the LRU lock to flush the dquot */
+               spin_unlock(lru_lock);
+
+               error = xfs_qm_dqflush(dqp, &bp);
+               if (error) {
+                       xfs_warn(dqp->q_mount, "%s: dquot %p flush failed",
+                                __func__, dqp);
+                       goto out_unlock_dirty;
+               }
+
+               xfs_buf_delwri_queue(bp, &isol->buffers);
+               xfs_buf_relse(bp);
+               goto out_unlock_dirty;
+       }
+       xfs_dqfunlock(dqp);
+
+       /*
+        * Prevent lookups now that we are past the point of no return.
+        */
+       dqp->dq_flags |= XFS_DQ_FREEING;
+       xfs_dqunlock(dqp);
+
+       ASSERT(dqp->q_nrefs == 0);
+       list_move_tail(&dqp->q_lru, &isol->dispose);
+       XFS_STATS_DEC(xs_qm_dquot_unused);
+       trace_xfs_dqreclaim_done(dqp);
+       XFS_STATS_INC(xs_qm_dqreclaims);
+       return 0;
+
+out_miss_busy:
+       trace_xfs_dqreclaim_busy(dqp);
+       XFS_STATS_INC(xs_qm_dqreclaim_misses);
+       return 2;
+
+out_unlock_dirty:
+       trace_xfs_dqreclaim_busy(dqp);
+       XFS_STATS_INC(xs_qm_dqreclaim_misses);
+       return 3;
+}
+
+static long
+xfs_qm_shrink_scan(
+       struct shrinker         *shrink,
+       struct shrink_control   *sc)
+{
+       struct xfs_quotainfo    *qi = container_of(shrink,
+                                       struct xfs_quotainfo, qi_shrinker);
+       struct xfs_qm_isolate   isol;
+       long                    freed;
+       int                     error;
+       unsigned long           nr_to_scan = sc->nr_to_scan;
+
+       if ((sc->gfp_mask & (__GFP_FS|__GFP_WAIT)) != (__GFP_FS|__GFP_WAIT))
+               return 0;
+
+       INIT_LIST_HEAD(&isol.buffers);
+       INIT_LIST_HEAD(&isol.dispose);
+
+       freed = list_lru_walk_node(&qi->qi_lru, sc->nid, xfs_qm_dquot_isolate, 
&isol,
+                                       &nr_to_scan);
+
+       error = xfs_buf_delwri_submit(&isol.buffers);
+       if (error)
+               xfs_warn(NULL, "%s: dquot reclaim failed", __func__);
+
+       while (!list_empty(&isol.dispose)) {
+               struct xfs_dquot        *dqp;
+
+               dqp = list_first_entry(&isol.dispose, struct xfs_dquot, q_lru);
+               list_del_init(&dqp->q_lru);
+               xfs_qm_dqfree_one(dqp);
+       }
+
+       return freed;
+}
+
+static long
+xfs_qm_shrink_count(
+       struct shrinker         *shrink,
+       struct shrink_control   *sc)
+{
+       struct xfs_quotainfo    *qi = container_of(shrink,
+                                       struct xfs_quotainfo, qi_shrinker);
+
+       return list_lru_count_node(&qi->qi_lru, sc->nid);
+}
+
 /*
  * This initializes all the quota information that's kept in the
  * mount structure
@@ -462,8 +595,7 @@ xfs_qm_init_quotainfo(
        INIT_RADIX_TREE(&qinf->qi_pquota_tree, GFP_NOFS);
        mutex_init(&qinf->qi_tree_lock);
 
-       INIT_LIST_HEAD(&qinf->qi_lru_list);
-       qinf->qi_lru_count = 0;
+       list_lru_init(&qinf->qi_lru);
 
        /* mutex used to serialize quotaoffs */
        mutex_init(&qinf->qi_quotaofflock);
@@ -528,8 +660,10 @@ xfs_qm_init_quotainfo(
                qinf->qi_rtbwarnlimit = XFS_QM_RTBWARNLIMIT;
        }
 
-       qinf->qi_shrinker.shrink = xfs_qm_shake;
+       qinf->qi_shrinker.count_objects = xfs_qm_shrink_count;
+       qinf->qi_shrinker.scan_objects = xfs_qm_shrink_scan;
        qinf->qi_shrinker.seeks = DEFAULT_SEEKS;
+       qinf->qi_shrinker.flags = SHRINKER_NUMA_AWARE;
        register_shrinker(&qinf->qi_shrinker);
        return 0;
 }
@@ -1447,132 +1581,6 @@ xfs_qm_dqfree_one(
        xfs_qm_dqdestroy(dqp);
 }
 
-STATIC void
-xfs_qm_dqreclaim_one(
-       struct xfs_dquot        *dqp,
-       struct list_head        *buffer_list,
-       struct list_head        *dispose_list)
-{
-       struct xfs_mount        *mp = dqp->q_mount;
-       struct xfs_quotainfo    *qi = mp->m_quotainfo;
-       int                     error;
-
-       if (!xfs_dqlock_nowait(dqp))
-               goto out_move_tail;
-
-       /*
-        * This dquot has acquired a reference in the meantime remove it from
-        * the freelist and try again.
-        */
-       if (dqp->q_nrefs) {
-               xfs_dqunlock(dqp);
-
-               trace_xfs_dqreclaim_want(dqp);
-               XFS_STATS_INC(xs_qm_dqwants);
-
-               list_del_init(&dqp->q_lru);
-               qi->qi_lru_count--;
-               XFS_STATS_DEC(xs_qm_dquot_unused);
-               return;
-       }
-
-       /*
-        * Try to grab the flush lock. If this dquot is in the process of
-        * getting flushed to disk, we don't want to reclaim it.
-        */
-       if (!xfs_dqflock_nowait(dqp))
-               goto out_unlock_move_tail;
-
-       if (XFS_DQ_IS_DIRTY(dqp)) {
-               struct xfs_buf  *bp = NULL;
-
-               trace_xfs_dqreclaim_dirty(dqp);
-
-               error = xfs_qm_dqflush(dqp, &bp);
-               if (error) {
-                       xfs_warn(mp, "%s: dquot %p flush failed",
-                                __func__, dqp);
-                       goto out_unlock_move_tail;
-               }
-
-               xfs_buf_delwri_queue(bp, buffer_list);
-               xfs_buf_relse(bp);
-               /*
-                * Give the dquot another try on the freelist, as the
-                * flushing will take some time.
-                */
-               goto out_unlock_move_tail;
-       }
-       xfs_dqfunlock(dqp);
-
-       /*
-        * Prevent lookups now that we are past the point of no return.
-        */
-       dqp->dq_flags |= XFS_DQ_FREEING;
-       xfs_dqunlock(dqp);
-
-       ASSERT(dqp->q_nrefs == 0);
-       list_move_tail(&dqp->q_lru, dispose_list);
-       qi->qi_lru_count--;
-       XFS_STATS_DEC(xs_qm_dquot_unused);
-
-       trace_xfs_dqreclaim_done(dqp);
-       XFS_STATS_INC(xs_qm_dqreclaims);
-       return;
-
-       /*
-        * Move the dquot to the tail of the list so that we don't spin on it.
-        */
-out_unlock_move_tail:
-       xfs_dqunlock(dqp);
-out_move_tail:
-       list_move_tail(&dqp->q_lru, &qi->qi_lru_list);
-       trace_xfs_dqreclaim_busy(dqp);
-       XFS_STATS_INC(xs_qm_dqreclaim_misses);
-}
-
-STATIC int
-xfs_qm_shake(
-       struct shrinker         *shrink,
-       struct shrink_control   *sc)
-{
-       struct xfs_quotainfo    *qi =
-               container_of(shrink, struct xfs_quotainfo, qi_shrinker);
-       int                     nr_to_scan = sc->nr_to_scan;
-       LIST_HEAD               (buffer_list);
-       LIST_HEAD               (dispose_list);
-       struct xfs_dquot        *dqp;
-       int                     error;
-
-       if ((sc->gfp_mask & (__GFP_FS|__GFP_WAIT)) != (__GFP_FS|__GFP_WAIT))
-               return 0;
-       if (!nr_to_scan)
-               goto out;
-
-       mutex_lock(&qi->qi_lru_lock);
-       while (!list_empty(&qi->qi_lru_list)) {
-               if (nr_to_scan-- <= 0)
-                       break;
-               dqp = list_first_entry(&qi->qi_lru_list, struct xfs_dquot,
-                                      q_lru);
-               xfs_qm_dqreclaim_one(dqp, &buffer_list, &dispose_list);
-       }
-       mutex_unlock(&qi->qi_lru_lock);
-
-       error = xfs_buf_delwri_submit(&buffer_list);
-       if (error)
-               xfs_warn(NULL, "%s: dquot reclaim failed", __func__);
-
-       while (!list_empty(&dispose_list)) {
-               dqp = list_first_entry(&dispose_list, struct xfs_dquot, q_lru);
-               list_del_init(&dqp->q_lru);
-               xfs_qm_dqfree_one(dqp);
-       }
-
-out:
-       return vfs_pressure_ratio(qi->qi_lru_count);
-}
-
 /* --------------- utility functions for vnodeops ---------------- */
 
 
diff --git a/fs/xfs/xfs_qm.h b/fs/xfs/xfs_qm.h
index e9653b0..d6e4d88 100644
--- a/fs/xfs/xfs_qm.h
+++ b/fs/xfs/xfs_qm.h
@@ -65,9 +65,7 @@ typedef struct xfs_quotainfo {
        struct xfs_inode        *qi_uquotaip;   /* user quota inode */
        struct xfs_inode        *qi_gquotaip;   /* group quota inode */
        struct xfs_inode        *qi_pquotaip;   /* project quota inode */
-       struct list_head qi_lru_list;
-       struct mutex     qi_lru_lock;
-       int              qi_lru_count;
+       struct list_lru  qi_lru;
        int              qi_dquots;
        time_t           qi_btimelimit;  /* limit for blks timer */
        time_t           qi_itimelimit;  /* limit for inodes timer */
_______________________________________________
Devel mailing list
Devel@openvz.org
https://lists.openvz.org/mailman/listinfo/devel

Reply via email to