diff options
-rw-r--r-- | fs/xfs/quota/xfs_qm.c | 46 |
1 files changed, 21 insertions, 25 deletions
diff --git a/fs/xfs/quota/xfs_qm.c b/fs/xfs/quota/xfs_qm.c index f8e854b4fde8..206a2815ced6 100644 --- a/fs/xfs/quota/xfs_qm.c +++ b/fs/xfs/quota/xfs_qm.c | |||
@@ -1863,12 +1863,14 @@ xfs_qm_dqreclaim_one(void) | |||
1863 | xfs_dquot_t *dqpout; | 1863 | xfs_dquot_t *dqpout; |
1864 | xfs_dquot_t *dqp; | 1864 | xfs_dquot_t *dqp; |
1865 | int restarts; | 1865 | int restarts; |
1866 | int startagain; | ||
1866 | 1867 | ||
1867 | restarts = 0; | 1868 | restarts = 0; |
1868 | dqpout = NULL; | 1869 | dqpout = NULL; |
1869 | 1870 | ||
1870 | /* lockorder: hashchainlock, freelistlock, mplistlock, dqlock, dqflock */ | 1871 | /* lockorder: hashchainlock, freelistlock, mplistlock, dqlock, dqflock */ |
1871 | startagain: | 1872 | again: |
1873 | startagain = 0; | ||
1872 | mutex_lock(&xfs_Gqm->qm_dqfrlist_lock); | 1874 | mutex_lock(&xfs_Gqm->qm_dqfrlist_lock); |
1873 | 1875 | ||
1874 | list_for_each_entry(dqp, &xfs_Gqm->qm_dqfrlist, q_freelist) { | 1876 | list_for_each_entry(dqp, &xfs_Gqm->qm_dqfrlist, q_freelist) { |
@@ -1885,13 +1887,10 @@ startagain: | |||
1885 | ASSERT(! (dqp->dq_flags & XFS_DQ_INACTIVE)); | 1887 | ASSERT(! (dqp->dq_flags & XFS_DQ_INACTIVE)); |
1886 | 1888 | ||
1887 | trace_xfs_dqreclaim_want(dqp); | 1889 | trace_xfs_dqreclaim_want(dqp); |
1888 | |||
1889 | xfs_dqunlock(dqp); | ||
1890 | mutex_unlock(&xfs_Gqm->qm_dqfrlist_lock); | ||
1891 | if (++restarts >= XFS_QM_RECLAIM_MAX_RESTARTS) | ||
1892 | return NULL; | ||
1893 | XQM_STATS_INC(xqmstats.xs_qm_dqwants); | 1890 | XQM_STATS_INC(xqmstats.xs_qm_dqwants); |
1894 | goto startagain; | 1891 | restarts++; |
1892 | startagain = 1; | ||
1893 | goto dqunlock; | ||
1895 | } | 1894 | } |
1896 | 1895 | ||
1897 | /* | 1896 | /* |
@@ -1906,23 +1905,20 @@ startagain: | |||
1906 | ASSERT(list_empty(&dqp->q_mplist)); | 1905 | ASSERT(list_empty(&dqp->q_mplist)); |
1907 | list_del_init(&dqp->q_freelist); | 1906 | list_del_init(&dqp->q_freelist); |
1908 | xfs_Gqm->qm_dqfrlist_cnt--; | 1907 | xfs_Gqm->qm_dqfrlist_cnt--; |
1909 | xfs_dqunlock(dqp); | ||
1910 | dqpout = dqp; | 1908 | dqpout = dqp; |
1911 | XQM_STATS_INC(xqmstats.xs_qm_dqinact_reclaims); | 1909 | XQM_STATS_INC(xqmstats.xs_qm_dqinact_reclaims); |
1912 | break; | 1910 | goto dqunlock; |
1913 | } | 1911 | } |
1914 | 1912 | ||
1915 | ASSERT(dqp->q_hash); | 1913 | ASSERT(dqp->q_hash); |
1916 | ASSERT(!list_empty(&dqp->q_mplist)); | 1914 | ASSERT(!list_empty(&dqp->q_mplist)); |
1917 | 1915 | ||
1918 | /* | 1916 | /* |
1919 | * Try to grab the flush lock. If this dquot is in the process of | 1917 | * Try to grab the flush lock. If this dquot is in the process |
1920 | * getting flushed to disk, we don't want to reclaim it. | 1918 | * of getting flushed to disk, we don't want to reclaim it. |
1921 | */ | 1919 | */ |
1922 | if (!xfs_dqflock_nowait(dqp)) { | 1920 | if (!xfs_dqflock_nowait(dqp)) |
1923 | xfs_dqunlock(dqp); | 1921 | goto dqunlock; |
1924 | continue; | ||
1925 | } | ||
1926 | 1922 | ||
1927 | /* | 1923 | /* |
1928 | * We have the flush lock so we know that this is not in the | 1924 | * We have the flush lock so we know that this is not in the |
@@ -1944,8 +1940,7 @@ startagain: | |||
1944 | xfs_fs_cmn_err(CE_WARN, mp, | 1940 | xfs_fs_cmn_err(CE_WARN, mp, |
1945 | "xfs_qm_dqreclaim: dquot %p flush failed", dqp); | 1941 | "xfs_qm_dqreclaim: dquot %p flush failed", dqp); |
1946 | } | 1942 | } |
1947 | xfs_dqunlock(dqp); /* dqflush unlocks dqflock */ | 1943 | goto dqunlock; |
1948 | continue; | ||
1949 | } | 1944 | } |
1950 | 1945 | ||
1951 | /* | 1946 | /* |
@@ -1967,13 +1962,8 @@ startagain: | |||
1967 | */ | 1962 | */ |
1968 | if (!mutex_trylock(&mp->m_quotainfo->qi_dqlist_lock)) { | 1963 | if (!mutex_trylock(&mp->m_quotainfo->qi_dqlist_lock)) { |
1969 | restarts++; | 1964 | restarts++; |
1970 | mutex_unlock(&dqp->q_hash->qh_lock); | 1965 | startagain = 1; |
1971 | xfs_dqfunlock(dqp); | 1966 | goto qhunlock; |
1972 | xfs_dqunlock(dqp); | ||
1973 | mutex_unlock(&xfs_Gqm->qm_dqfrlist_lock); | ||
1974 | if (restarts++ >= XFS_QM_RECLAIM_MAX_RESTARTS) | ||
1975 | return NULL; | ||
1976 | goto startagain; | ||
1977 | } | 1967 | } |
1978 | 1968 | ||
1979 | ASSERT(dqp->q_nrefs == 0); | 1969 | ASSERT(dqp->q_nrefs == 0); |
@@ -1986,14 +1976,20 @@ startagain: | |||
1986 | xfs_Gqm->qm_dqfrlist_cnt--; | 1976 | xfs_Gqm->qm_dqfrlist_cnt--; |
1987 | dqpout = dqp; | 1977 | dqpout = dqp; |
1988 | mutex_unlock(&mp->m_quotainfo->qi_dqlist_lock); | 1978 | mutex_unlock(&mp->m_quotainfo->qi_dqlist_lock); |
1979 | qhunlock: | ||
1989 | mutex_unlock(&dqp->q_hash->qh_lock); | 1980 | mutex_unlock(&dqp->q_hash->qh_lock); |
1990 | dqfunlock: | 1981 | dqfunlock: |
1991 | xfs_dqfunlock(dqp); | 1982 | xfs_dqfunlock(dqp); |
1983 | dqunlock: | ||
1992 | xfs_dqunlock(dqp); | 1984 | xfs_dqunlock(dqp); |
1993 | if (dqpout) | 1985 | if (dqpout) |
1994 | break; | 1986 | break; |
1995 | if (restarts >= XFS_QM_RECLAIM_MAX_RESTARTS) | 1987 | if (restarts >= XFS_QM_RECLAIM_MAX_RESTARTS) |
1996 | return NULL; | 1988 | break; |
1989 | if (startagain) { | ||
1990 | mutex_unlock(&xfs_Gqm->qm_dqfrlist_lock); | ||
1991 | goto again; | ||
1992 | } | ||
1997 | } | 1993 | } |
1998 | mutex_unlock(&xfs_Gqm->qm_dqfrlist_lock); | 1994 | mutex_unlock(&xfs_Gqm->qm_dqfrlist_lock); |
1999 | return dqpout; | 1995 | return dqpout; |