aboutsummaryrefslogtreecommitdiffstats
path: root/fs/xfs/quota/xfs_qm.c
diff options
context:
space:
mode:
Diffstat (limited to 'fs/xfs/quota/xfs_qm.c')
-rw-r--r--fs/xfs/quota/xfs_qm.c264
1 files changed, 73 insertions, 191 deletions
diff --git a/fs/xfs/quota/xfs_qm.c b/fs/xfs/quota/xfs_qm.c
index 855827320ff6..5ca65c834bbd 100644
--- a/fs/xfs/quota/xfs_qm.c
+++ b/fs/xfs/quota/xfs_qm.c
@@ -1926,53 +1926,46 @@ xfs_qm_init_quotainos(
1926} 1926}
1927 1927
1928 1928
1929
1929/* 1930/*
1930 * Traverse the freelist of dquots and attempt to reclaim a maximum of 1931 * Just pop the least recently used dquot off the freelist and
1931 * 'howmany' dquots. This operation races with dqlookup(), and attempts to 1932 * recycle it. The returned dquot is locked.
1932 * favor the lookup function ...
1933 * XXXsup merge this with qm_reclaim_one().
1934 */ 1933 */
1935STATIC int 1934STATIC xfs_dquot_t *
1936xfs_qm_shake_freelist( 1935xfs_qm_dqreclaim_one(void)
1937 int howmany)
1938{ 1936{
1939 int nreclaimed; 1937 xfs_dquot_t *dqpout;
1940 xfs_dqhash_t *hash; 1938 xfs_dquot_t *dqp;
1941 xfs_dquot_t *dqp, *nextdqp;
1942 int restarts; 1939 int restarts;
1943 int nflushes;
1944 1940
1945 if (howmany <= 0)
1946 return 0;
1947
1948 nreclaimed = 0;
1949 restarts = 0; 1941 restarts = 0;
1950 nflushes = 0; 1942 dqpout = NULL;
1951 1943
1952#ifdef QUOTADEBUG 1944 /* lockorder: hashchainlock, freelistlock, mplistlock, dqlock, dqflock */
1953 cmn_err(CE_DEBUG, "Shake free 0x%x", howmany); 1945startagain:
1954#endif
1955 /* lock order is : hashchainlock, freelistlock, mplistlock */
1956 tryagain:
1957 xfs_qm_freelist_lock(xfs_Gqm); 1946 xfs_qm_freelist_lock(xfs_Gqm);
1958 1947
1959 for (dqp = xfs_Gqm->qm_dqfreelist.qh_next; 1948 FOREACH_DQUOT_IN_FREELIST(dqp, &(xfs_Gqm->qm_dqfreelist)) {
1960 ((dqp != (xfs_dquot_t *) &xfs_Gqm->qm_dqfreelist) &&
1961 nreclaimed < howmany); ) {
1962 struct xfs_mount *mp = dqp->q_mount; 1949 struct xfs_mount *mp = dqp->q_mount;
1963 xfs_dqlock(dqp); 1950 xfs_dqlock(dqp);
1964 1951
1965 /* 1952 /*
1966 * We are racing with dqlookup here. Naturally we don't 1953 * We are racing with dqlookup here. Naturally we don't
1967 * want to reclaim a dquot that lookup wants. 1954 * want to reclaim a dquot that lookup wants. We release the
1955 * freelist lock and start over, so that lookup will grab
1956 * both the dquot and the freelistlock.
1968 */ 1957 */
1969 if (dqp->dq_flags & XFS_DQ_WANT) { 1958 if (dqp->dq_flags & XFS_DQ_WANT) {
1959 ASSERT(! (dqp->dq_flags & XFS_DQ_INACTIVE));
1960
1961 trace_xfs_dqreclaim_want(dqp);
1962
1970 xfs_dqunlock(dqp); 1963 xfs_dqunlock(dqp);
1971 xfs_qm_freelist_unlock(xfs_Gqm); 1964 xfs_qm_freelist_unlock(xfs_Gqm);
1972 if (++restarts >= XFS_QM_RECLAIM_MAX_RESTARTS) 1965 if (++restarts >= XFS_QM_RECLAIM_MAX_RESTARTS)
1973 return nreclaimed; 1966 return NULL;
1974 XQM_STATS_INC(xqmstats.xs_qm_dqwants); 1967 XQM_STATS_INC(xqmstats.xs_qm_dqwants);
1975 goto tryagain; 1968 goto startagain;
1976 } 1969 }
1977 1970
1978 /* 1971 /*
@@ -1985,19 +1978,22 @@ xfs_qm_shake_freelist(
1985 ASSERT(! XFS_DQ_IS_DIRTY(dqp)); 1978 ASSERT(! XFS_DQ_IS_DIRTY(dqp));
1986 ASSERT(dqp->HL_PREVP == NULL); 1979 ASSERT(dqp->HL_PREVP == NULL);
1987 ASSERT(list_empty(&dqp->q_mplist)); 1980 ASSERT(list_empty(&dqp->q_mplist));
1981 XQM_FREELIST_REMOVE(dqp);
1982 xfs_dqunlock(dqp);
1983 dqpout = dqp;
1988 XQM_STATS_INC(xqmstats.xs_qm_dqinact_reclaims); 1984 XQM_STATS_INC(xqmstats.xs_qm_dqinact_reclaims);
1989 nextdqp = dqp->dq_flnext; 1985 break;
1990 goto off_freelist;
1991 } 1986 }
1992 1987
1988 ASSERT(dqp->q_hash);
1993 ASSERT(!list_empty(&dqp->q_mplist)); 1989 ASSERT(!list_empty(&dqp->q_mplist));
1990
1994 /* 1991 /*
1995 * Try to grab the flush lock. If this dquot is in the process of 1992 * Try to grab the flush lock. If this dquot is in the process of
1996 * getting flushed to disk, we don't want to reclaim it. 1993 * getting flushed to disk, we don't want to reclaim it.
1997 */ 1994 */
1998 if (!xfs_dqflock_nowait(dqp)) { 1995 if (!xfs_dqflock_nowait(dqp)) {
1999 xfs_dqunlock(dqp); 1996 xfs_dqunlock(dqp);
2000 dqp = dqp->dq_flnext;
2001 continue; 1997 continue;
2002 } 1998 }
2003 1999
@@ -2010,21 +2006,21 @@ xfs_qm_shake_freelist(
2010 if (XFS_DQ_IS_DIRTY(dqp)) { 2006 if (XFS_DQ_IS_DIRTY(dqp)) {
2011 int error; 2007 int error;
2012 2008
2013 trace_xfs_dqshake_dirty(dqp); 2009 trace_xfs_dqreclaim_dirty(dqp);
2014 2010
2015 /* 2011 /*
2016 * We flush it delayed write, so don't bother 2012 * We flush it delayed write, so don't bother
2017 * releasing the mplock. 2013 * releasing the freelist lock.
2018 */ 2014 */
2019 error = xfs_qm_dqflush(dqp, 0); 2015 error = xfs_qm_dqflush(dqp, 0);
2020 if (error) { 2016 if (error) {
2021 xfs_fs_cmn_err(CE_WARN, mp, 2017 xfs_fs_cmn_err(CE_WARN, mp,
2022 "xfs_qm_dqflush_all: dquot %p flush failed", dqp); 2018 "xfs_qm_dqreclaim: dquot %p flush failed", dqp);
2023 } 2019 }
2024 xfs_dqunlock(dqp); /* dqflush unlocks dqflock */ 2020 xfs_dqunlock(dqp); /* dqflush unlocks dqflock */
2025 dqp = dqp->dq_flnext;
2026 continue; 2021 continue;
2027 } 2022 }
2023
2028 /* 2024 /*
2029 * We're trying to get the hashlock out of order. This races 2025 * We're trying to get the hashlock out of order. This races
2030 * with dqlookup; so, we giveup and goto the next dquot if 2026 * with dqlookup; so, we giveup and goto the next dquot if
@@ -2033,57 +2029,71 @@ xfs_qm_shake_freelist(
2033 * waiting for the freelist lock. 2029 * waiting for the freelist lock.
2034 */ 2030 */
2035 if (!mutex_trylock(&dqp->q_hash->qh_lock)) { 2031 if (!mutex_trylock(&dqp->q_hash->qh_lock)) {
2036 xfs_dqfunlock(dqp); 2032 restarts++;
2037 xfs_dqunlock(dqp); 2033 goto dqfunlock;
2038 dqp = dqp->dq_flnext;
2039 continue;
2040 } 2034 }
2035
2041 /* 2036 /*
2042 * This races with dquot allocation code as well as dqflush_all 2037 * This races with dquot allocation code as well as dqflush_all
2043 * and reclaim code. So, if we failed to grab the mplist lock, 2038 * and reclaim code. So, if we failed to grab the mplist lock,
2044 * giveup everything and start over. 2039 * giveup everything and start over.
2045 */ 2040 */
2046 hash = dqp->q_hash;
2047 ASSERT(hash);
2048 if (!mutex_trylock(&mp->m_quotainfo->qi_dqlist_lock)) { 2041 if (!mutex_trylock(&mp->m_quotainfo->qi_dqlist_lock)) {
2049 /* XXX put a sentinel so that we can come back here */ 2042 restarts++;
2043 mutex_unlock(&dqp->q_hash->qh_lock);
2050 xfs_dqfunlock(dqp); 2044 xfs_dqfunlock(dqp);
2051 xfs_dqunlock(dqp); 2045 xfs_dqunlock(dqp);
2052 mutex_unlock(&hash->qh_lock);
2053 xfs_qm_freelist_unlock(xfs_Gqm); 2046 xfs_qm_freelist_unlock(xfs_Gqm);
2054 if (++restarts >= XFS_QM_RECLAIM_MAX_RESTARTS) 2047 if (restarts++ >= XFS_QM_RECLAIM_MAX_RESTARTS)
2055 return nreclaimed; 2048 return NULL;
2056 goto tryagain; 2049 goto startagain;
2057 } 2050 }
2058 2051
2059 trace_xfs_dqshake_unlink(dqp);
2060
2061#ifdef QUOTADEBUG
2062 cmn_err(CE_DEBUG, "Shake 0x%p, ID 0x%x\n",
2063 dqp, be32_to_cpu(dqp->q_core.d_id));
2064#endif
2065 ASSERT(dqp->q_nrefs == 0); 2052 ASSERT(dqp->q_nrefs == 0);
2066 nextdqp = dqp->dq_flnext;
2067 XQM_HASHLIST_REMOVE(hash, dqp);
2068 list_del_init(&dqp->q_mplist); 2053 list_del_init(&dqp->q_mplist);
2069 mp->m_quotainfo->qi_dquots--; 2054 mp->m_quotainfo->qi_dquots--;
2070 mp->m_quotainfo->qi_dqreclaims++; 2055 mp->m_quotainfo->qi_dqreclaims++;
2071 xfs_dqfunlock(dqp); 2056 XQM_HASHLIST_REMOVE(dqp->q_hash, dqp);
2072 mutex_unlock(&mp->m_quotainfo->qi_dqlist_lock);
2073 mutex_unlock(&hash->qh_lock);
2074
2075 off_freelist:
2076 XQM_FREELIST_REMOVE(dqp); 2057 XQM_FREELIST_REMOVE(dqp);
2058 dqpout = dqp;
2059 mutex_unlock(&mp->m_quotainfo->qi_dqlist_lock);
2060 mutex_unlock(&dqp->q_hash->qh_lock);
2061dqfunlock:
2062 xfs_dqfunlock(dqp);
2077 xfs_dqunlock(dqp); 2063 xfs_dqunlock(dqp);
2078 nreclaimed++; 2064 if (dqpout)
2079 XQM_STATS_INC(xqmstats.xs_qm_dqshake_reclaims); 2065 break;
2080 xfs_qm_dqdestroy(dqp); 2066 if (restarts >= XFS_QM_RECLAIM_MAX_RESTARTS)
2081 dqp = nextdqp; 2067 return NULL;
2082 } 2068 }
2083 xfs_qm_freelist_unlock(xfs_Gqm); 2069 xfs_qm_freelist_unlock(xfs_Gqm);
2084 return nreclaimed; 2070 return dqpout;
2085} 2071}
2086 2072
2073/*
2074 * Traverse the freelist of dquots and attempt to reclaim a maximum of
2075 * 'howmany' dquots. This operation races with dqlookup(), and attempts to
2076 * favor the lookup function ...
2077 */
2078STATIC int
2079xfs_qm_shake_freelist(
2080 int howmany)
2081{
2082 int nreclaimed = 0;
2083 xfs_dquot_t *dqp;
2084
2085 if (howmany <= 0)
2086 return 0;
2087
2088 while (nreclaimed < howmany) {
2089 dqp = xfs_qm_dqreclaim_one();
2090 if (!dqp)
2091 return nreclaimed;
2092 xfs_qm_dqdestroy(dqp);
2093 nreclaimed++;
2094 }
2095 return nreclaimed;
2096}
2087 2097
2088/* 2098/*
2089 * The kmem_shake interface is invoked when memory is running low. 2099 * The kmem_shake interface is invoked when memory is running low.
@@ -2115,134 +2125,6 @@ xfs_qm_shake(int nr_to_scan, gfp_t gfp_mask)
2115} 2125}
2116 2126
2117 2127
2118/*
2119 * Just pop the least recently used dquot off the freelist and
2120 * recycle it. The returned dquot is locked.
2121 */
2122STATIC xfs_dquot_t *
2123xfs_qm_dqreclaim_one(void)
2124{
2125 xfs_dquot_t *dqpout;
2126 xfs_dquot_t *dqp;
2127 int restarts;
2128 int nflushes;
2129
2130 restarts = 0;
2131 dqpout = NULL;
2132 nflushes = 0;
2133
2134 /* lockorder: hashchainlock, freelistlock, mplistlock, dqlock, dqflock */
2135 startagain:
2136 xfs_qm_freelist_lock(xfs_Gqm);
2137
2138 FOREACH_DQUOT_IN_FREELIST(dqp, &(xfs_Gqm->qm_dqfreelist)) {
2139 struct xfs_mount *mp = dqp->q_mount;
2140 xfs_dqlock(dqp);
2141
2142 /*
2143 * We are racing with dqlookup here. Naturally we don't
2144 * want to reclaim a dquot that lookup wants. We release the
2145 * freelist lock and start over, so that lookup will grab
2146 * both the dquot and the freelistlock.
2147 */
2148 if (dqp->dq_flags & XFS_DQ_WANT) {
2149 ASSERT(! (dqp->dq_flags & XFS_DQ_INACTIVE));
2150
2151 trace_xfs_dqreclaim_want(dqp);
2152
2153 xfs_dqunlock(dqp);
2154 xfs_qm_freelist_unlock(xfs_Gqm);
2155 if (++restarts >= XFS_QM_RECLAIM_MAX_RESTARTS)
2156 return NULL;
2157 XQM_STATS_INC(xqmstats.xs_qm_dqwants);
2158 goto startagain;
2159 }
2160
2161 /*
2162 * If the dquot is inactive, we are assured that it is
2163 * not on the mplist or the hashlist, and that makes our
2164 * life easier.
2165 */
2166 if (dqp->dq_flags & XFS_DQ_INACTIVE) {
2167 ASSERT(mp == NULL);
2168 ASSERT(! XFS_DQ_IS_DIRTY(dqp));
2169 ASSERT(dqp->HL_PREVP == NULL);
2170 ASSERT(list_empty(&dqp->q_mplist));
2171 XQM_FREELIST_REMOVE(dqp);
2172 xfs_dqunlock(dqp);
2173 dqpout = dqp;
2174 XQM_STATS_INC(xqmstats.xs_qm_dqinact_reclaims);
2175 break;
2176 }
2177
2178 ASSERT(dqp->q_hash);
2179 ASSERT(!list_empty(&dqp->q_mplist));
2180
2181 /*
2182 * Try to grab the flush lock. If this dquot is in the process of
2183 * getting flushed to disk, we don't want to reclaim it.
2184 */
2185 if (!xfs_dqflock_nowait(dqp)) {
2186 xfs_dqunlock(dqp);
2187 continue;
2188 }
2189
2190 /*
2191 * We have the flush lock so we know that this is not in the
2192 * process of being flushed. So, if this is dirty, flush it
2193 * DELWRI so that we don't get a freelist infested with
2194 * dirty dquots.
2195 */
2196 if (XFS_DQ_IS_DIRTY(dqp)) {
2197 int error;
2198
2199 trace_xfs_dqreclaim_dirty(dqp);
2200
2201 /*
2202 * We flush it delayed write, so don't bother
2203 * releasing the freelist lock.
2204 */
2205 error = xfs_qm_dqflush(dqp, 0);
2206 if (error) {
2207 xfs_fs_cmn_err(CE_WARN, mp,
2208 "xfs_qm_dqreclaim: dquot %p flush failed", dqp);
2209 }
2210 xfs_dqunlock(dqp); /* dqflush unlocks dqflock */
2211 continue;
2212 }
2213
2214 if (!mutex_trylock(&mp->m_quotainfo->qi_dqlist_lock)) {
2215 xfs_dqfunlock(dqp);
2216 xfs_dqunlock(dqp);
2217 continue;
2218 }
2219
2220 if (!mutex_trylock(&dqp->q_hash->qh_lock))
2221 goto mplistunlock;
2222
2223 trace_xfs_dqreclaim_unlink(dqp);
2224
2225 ASSERT(dqp->q_nrefs == 0);
2226 list_del_init(&dqp->q_mplist);
2227 mp->m_quotainfo->qi_dquots--;
2228 mp->m_quotainfo->qi_dqreclaims++;
2229 XQM_HASHLIST_REMOVE(dqp->q_hash, dqp);
2230 XQM_FREELIST_REMOVE(dqp);
2231 dqpout = dqp;
2232 mutex_unlock(&dqp->q_hash->qh_lock);
2233 mplistunlock:
2234 mutex_unlock(&mp->m_quotainfo->qi_dqlist_lock);
2235 xfs_dqfunlock(dqp);
2236 xfs_dqunlock(dqp);
2237 if (dqpout)
2238 break;
2239 }
2240
2241 xfs_qm_freelist_unlock(xfs_Gqm);
2242 return dqpout;
2243}
2244
2245
2246/*------------------------------------------------------------------*/ 2128/*------------------------------------------------------------------*/
2247 2129
2248/* 2130/*