Commit b84a3a96 authored by Christoph Hellwig's avatar Christoph Hellwig Committed by Ben Myers

xfs: remove the per-filesystem list of dquots

Instead of keeping a separate per-filesystem list of dquots we can walk
the radix tree for the two places where we need to iterate all quota
structures.
Reviewed-by: default avatarDave Chinner <dchinner@redhat.com>
Signed-off-by: default avatarChristoph Hellwig <hch@lst.de>
Signed-off-by: default avatarBen Myers <bpm@sgi.com>
parent 9f920f11
...@@ -44,10 +44,9 @@ ...@@ -44,10 +44,9 @@
* *
* ip->i_lock * ip->i_lock
* qi->qi_tree_lock * qi->qi_tree_lock
* qi->qi_dqlist_lock * dquot->q_qlock (xfs_dqlock() and friends)
* dquot->q_qlock (xfs_dqlock() and friends) * dquot->q_flush (xfs_dqflock() and friends)
* dquot->q_flush (xfs_dqflock() and friends) * qi->qi_lru_lock
* qi->qi_lru_lock
* *
* If two dquots need to be locked the order is user before group/project, * If two dquots need to be locked the order is user before group/project,
* otherwise by the lowest id first, see xfs_dqlock2. * otherwise by the lowest id first, see xfs_dqlock2.
...@@ -728,21 +727,13 @@ xfs_qm_dqget( ...@@ -728,21 +727,13 @@ xfs_qm_dqget(
goto restart; goto restart;
} }
/*
* Attach this dquot to this filesystem's list of all dquots,
* kept inside the mount structure in m_quotainfo field
*/
mutex_lock(&qi->qi_dqlist_lock);
/* /*
* We return a locked dquot to the caller, with a reference taken * We return a locked dquot to the caller, with a reference taken
*/ */
xfs_dqlock(dqp); xfs_dqlock(dqp);
dqp->q_nrefs = 1; dqp->q_nrefs = 1;
list_add(&dqp->q_mplist, &qi->qi_dqlist);
qi->qi_dquots++; qi->qi_dquots++;
mutex_unlock(&qi->qi_dqlist_lock);
mutex_unlock(&qi->qi_tree_lock); mutex_unlock(&qi->qi_tree_lock);
dqret: dqret:
...@@ -1017,86 +1008,6 @@ xfs_dqlock2( ...@@ -1017,86 +1008,6 @@ xfs_dqlock2(
} }
} }
/*
* Take a dquot out of the mount's dqlist as well as the hashlist. This is
* called via unmount as well as quotaoff, and the purge will always succeed.
*/
void
xfs_qm_dqpurge(
struct xfs_dquot *dqp)
{
struct xfs_mount *mp = dqp->q_mount;
struct xfs_quotainfo *qi = mp->m_quotainfo;
xfs_dqlock(dqp);
/*
* If we're turning off quotas, we have to make sure that, for
* example, we don't delete quota disk blocks while dquots are
* in the process of getting written to those disk blocks.
* This dquot might well be on AIL, and we can't leave it there
* if we're turning off quotas. Basically, we need this flush
* lock, and are willing to block on it.
*/
if (!xfs_dqflock_nowait(dqp)) {
/*
* Block on the flush lock after nudging dquot buffer,
* if it is incore.
*/
xfs_dqflock_pushbuf_wait(dqp);
}
/*
* If we are turning this type of quotas off, we don't care
* about the dirty metadata sitting in this dquot. OTOH, if
* we're unmounting, we do care, so we flush it and wait.
*/
if (XFS_DQ_IS_DIRTY(dqp)) {
int error;
/*
* We don't care about getting disk errors here. We need
* to purge this dquot anyway, so we go ahead regardless.
*/
error = xfs_qm_dqflush(dqp, SYNC_WAIT);
if (error)
xfs_warn(mp, "%s: dquot %p flush failed",
__func__, dqp);
xfs_dqflock(dqp);
}
ASSERT(atomic_read(&dqp->q_pincount) == 0);
ASSERT(XFS_FORCED_SHUTDOWN(mp) ||
!(dqp->q_logitem.qli_item.li_flags & XFS_LI_IN_AIL));
xfs_dqfunlock(dqp);
xfs_dqunlock(dqp);
mutex_lock(&qi->qi_tree_lock);
radix_tree_delete(XFS_DQUOT_TREE(qi, dqp->q_core.d_flags),
be32_to_cpu(dqp->q_core.d_id));
mutex_unlock(&qi->qi_tree_lock);
mutex_lock(&qi->qi_dqlist_lock);
list_del_init(&dqp->q_mplist);
qi->qi_dqreclaims++;
qi->qi_dquots--;
mutex_unlock(&qi->qi_dqlist_lock);
/*
* 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--;
XFS_STATS_DEC(xs_qm_dquot_unused);
mutex_unlock(&qi->qi_lru_lock);
xfs_qm_dqdestroy(dqp);
}
/* /*
* Give the buffer a little push if it is incore and * Give the buffer a little push if it is incore and
* wait on the flush lock. * wait on the flush lock.
......
...@@ -38,7 +38,6 @@ struct xfs_trans; ...@@ -38,7 +38,6 @@ struct xfs_trans;
typedef struct xfs_dquot { typedef struct xfs_dquot {
uint dq_flags; /* various flags (XFS_DQ_*) */ uint dq_flags; /* various flags (XFS_DQ_*) */
struct list_head q_lru; /* global free list of dquots */ struct list_head q_lru; /* global free list of dquots */
struct list_head q_mplist; /* mount's list of dquots */
struct xfs_mount*q_mount; /* filesystem this relates to */ struct xfs_mount*q_mount; /* filesystem this relates to */
struct xfs_trans*q_transp; /* trans this belongs to currently */ struct xfs_trans*q_transp; /* trans this belongs to currently */
uint q_nrefs; /* # active refs from inodes */ uint q_nrefs; /* # active refs from inodes */
...@@ -143,7 +142,6 @@ extern int xfs_qm_dqread(struct xfs_mount *, xfs_dqid_t, uint, ...@@ -143,7 +142,6 @@ extern int xfs_qm_dqread(struct xfs_mount *, xfs_dqid_t, uint,
uint, struct xfs_dquot **); uint, struct xfs_dquot **);
extern void xfs_qm_dqdestroy(xfs_dquot_t *); extern void xfs_qm_dqdestroy(xfs_dquot_t *);
extern int xfs_qm_dqflush(xfs_dquot_t *, uint); extern int xfs_qm_dqflush(xfs_dquot_t *, uint);
extern void xfs_qm_dqpurge(xfs_dquot_t *);
extern void xfs_qm_dqunpin_wait(xfs_dquot_t *); extern void xfs_qm_dqunpin_wait(xfs_dquot_t *);
extern void xfs_qm_adjust_dqtimers(xfs_mount_t *, extern void xfs_qm_adjust_dqtimers(xfs_mount_t *,
xfs_disk_dquot_t *); xfs_disk_dquot_t *);
......
This diff is collapsed.
...@@ -63,11 +63,7 @@ typedef struct xfs_quotainfo { ...@@ -63,11 +63,7 @@ typedef struct xfs_quotainfo {
struct list_head qi_lru_list; struct list_head qi_lru_list;
struct mutex qi_lru_lock; struct mutex qi_lru_lock;
int qi_lru_count; int qi_lru_count;
struct list_head qi_dqlist; /* all dquots in filesys */
struct mutex qi_dqlist_lock;
int qi_dquots; int qi_dquots;
int qi_dqreclaims; /* a change here indicates
a removal in the dqlist */
time_t qi_btimelimit; /* limit for blks timer */ time_t qi_btimelimit; /* limit for blks timer */
time_t qi_itimelimit; /* limit for inodes timer */ time_t qi_itimelimit; /* limit for inodes timer */
time_t qi_rtbtimelimit;/* limit for rt blks timer */ time_t qi_rtbtimelimit;/* limit for rt blks timer */
...@@ -126,7 +122,7 @@ extern int xfs_qm_quotacheck(xfs_mount_t *); ...@@ -126,7 +122,7 @@ extern int xfs_qm_quotacheck(xfs_mount_t *);
extern int xfs_qm_write_sb_changes(xfs_mount_t *, __int64_t); extern int xfs_qm_write_sb_changes(xfs_mount_t *, __int64_t);
/* dquot stuff */ /* dquot stuff */
extern int xfs_qm_dqpurge_all(xfs_mount_t *, uint); extern void xfs_qm_dqpurge_all(xfs_mount_t *, uint);
extern void xfs_qm_dqrele_all_inodes(xfs_mount_t *, uint); extern void xfs_qm_dqrele_all_inodes(xfs_mount_t *, uint);
/* quota ops */ /* quota ops */
......
...@@ -66,7 +66,6 @@ xfs_qm_scall_quotaoff( ...@@ -66,7 +66,6 @@ xfs_qm_scall_quotaoff(
int error; int error;
uint inactivate_flags; uint inactivate_flags;
xfs_qoff_logitem_t *qoffstart; xfs_qoff_logitem_t *qoffstart;
int nculprits;
/* /*
* No file system can have quotas enabled on disk but not in core. * No file system can have quotas enabled on disk but not in core.
...@@ -172,18 +171,13 @@ xfs_qm_scall_quotaoff( ...@@ -172,18 +171,13 @@ xfs_qm_scall_quotaoff(
* This isn't protected by a particular lock directly, because we * This isn't protected by a particular lock directly, because we
* don't want to take a mrlock every time we depend on quotas being on. * don't want to take a mrlock every time we depend on quotas being on.
*/ */
mp->m_qflags &= ~(flags); mp->m_qflags &= ~flags;
/* /*
* Go through all the dquots of this file system and purge them, * Go through all the dquots of this file system and purge them,
* according to what was turned off. We may not be able to get rid * according to what was turned off.
* of all dquots, because dquots can have temporary references that
* are not attached to inodes. eg. xfs_setattr, xfs_create.
* So, if we couldn't purge all the dquots from the filesystem,
* we can't get rid of the incore data structures.
*/ */
while ((nculprits = xfs_qm_dqpurge_all(mp, dqtype))) xfs_qm_dqpurge_all(mp, dqtype);
delay(10 * nculprits);
/* /*
* Transactions that had started before ACTIVE state bit was cleared * Transactions that had started before ACTIVE state bit was cleared
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment