diff options
| author | Christoph Hellwig <hch@lst.de> | 2012-03-14 11:53:34 -0500 | 
|---|---|---|
| committer | Ben Myers <bpm@sgi.com> | 2012-03-14 11:53:34 -0500 | 
| commit | b84a3a96751f93071c1863f2962273973c8b8f5e (patch) | |
| tree | 26409cbc65a9b4457e6c52e90879361fc42d2386 /fs/xfs | |
| parent | 9f920f116426806bfa34c1422742e1bf7b7a2b4b (diff) | |
| download | linux-b84a3a96751f93071c1863f2962273973c8b8f5e.tar.bz2 | |
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: Dave Chinner <dchinner@redhat.com>
Signed-off-by: Christoph Hellwig <hch@lst.de>
Signed-off-by: Ben Myers <bpm@sgi.com>
Diffstat (limited to 'fs/xfs')
| -rw-r--r-- | fs/xfs/xfs_dquot.c | 95 | ||||
| -rw-r--r-- | fs/xfs/xfs_dquot.h | 2 | ||||
| -rw-r--r-- | fs/xfs/xfs_qm.c | 415 | ||||
| -rw-r--r-- | fs/xfs/xfs_qm.h | 6 | ||||
| -rw-r--r-- | fs/xfs/xfs_qm_syscalls.c | 12 | 
5 files changed, 226 insertions, 304 deletions
| diff --git a/fs/xfs/xfs_dquot.c b/fs/xfs/xfs_dquot.c index 49456e555cfa..2896ac953ed6 100644 --- a/fs/xfs/xfs_dquot.c +++ b/fs/xfs/xfs_dquot.c @@ -44,10 +44,9 @@   *   * ip->i_lock   *   qi->qi_tree_lock - *     qi->qi_dqlist_lock - *       dquot->q_qlock (xfs_dqlock() and friends) - *         dquot->q_flush (xfs_dqflock() and friends) - *         qi->qi_lru_lock + *     dquot->q_qlock (xfs_dqlock() and friends) + *       dquot->q_flush (xfs_dqflock() and friends) + *       qi->qi_lru_lock   *   * If two dquots need to be locked the order is user before group/project,   * otherwise by the lowest id first, see xfs_dqlock2. @@ -729,20 +728,12 @@ 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  	 */  	xfs_dqlock(dqp);  	dqp->q_nrefs = 1; -	list_add(&dqp->q_mplist, &qi->qi_dqlist);  	qi->qi_dquots++; -	mutex_unlock(&qi->qi_dqlist_lock);  	mutex_unlock(&qi->qi_tree_lock);   dqret: @@ -1018,86 +1009,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   * wait on the flush lock.   */ diff --git a/fs/xfs/xfs_dquot.h b/fs/xfs/xfs_dquot.h index 4061f1731271..ef9190bd8b30 100644 --- a/fs/xfs/xfs_dquot.h +++ b/fs/xfs/xfs_dquot.h @@ -38,7 +38,6 @@ struct xfs_trans;  typedef struct xfs_dquot {  	uint		 dq_flags;	/* various flags (XFS_DQ_*) */  	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_trans*q_transp;	/* trans this belongs to currently */  	uint		 q_nrefs;	/* # active refs from inodes */ @@ -143,7 +142,6 @@ extern int		xfs_qm_dqread(struct xfs_mount *, xfs_dqid_t, uint,  					uint, struct xfs_dquot	**);  extern void		xfs_qm_dqdestroy(xfs_dquot_t *);  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_adjust_dqtimers(xfs_mount_t *,  					xfs_disk_dquot_t *); diff --git a/fs/xfs/xfs_qm.c b/fs/xfs/xfs_qm.c index bb884e701cd9..2f92d3b0d8a8 100644 --- a/fs/xfs/xfs_qm.c +++ b/fs/xfs/xfs_qm.c @@ -169,6 +169,187 @@ xfs_qm_rele_quotafs_ref(  }  /* + * 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 + * fuzzy lookups instead of exact matches.  Holding the lock over multiple + * operations is fine as all callers are used either during mount/umount + * or quotaoff. + */ +#define XFS_DQ_LOOKUP_BATCH	32 + +STATIC int +xfs_qm_dquot_walk( +	struct xfs_mount	*mp, +	int			type, +	int			(*execute)(struct xfs_dquot *dqp)) +{ +	struct xfs_quotainfo	*qi = mp->m_quotainfo; +	struct radix_tree_root	*tree = XFS_DQUOT_TREE(qi, type); +	uint32_t		next_index; +	int			last_error = 0; +	int			skipped; +	int			nr_found; + +restart: +	skipped = 0; +	next_index = 0; +	nr_found = 0; + +	while (1) { +		struct xfs_dquot *batch[XFS_DQ_LOOKUP_BATCH]; +		int		error = 0; +		int		i; + +		mutex_lock(&qi->qi_tree_lock); +		nr_found = radix_tree_gang_lookup(tree, (void **)batch, +					next_index, XFS_DQ_LOOKUP_BATCH); +		if (!nr_found) { +			mutex_unlock(&qi->qi_tree_lock); +			break; +		} + +		for (i = 0; i < nr_found; i++) { +			struct xfs_dquot *dqp = batch[i]; + +			next_index = be32_to_cpu(dqp->q_core.d_id) + 1; + +			error = execute(batch[i]); +			if (error == EAGAIN) { +				skipped++; +				continue; +			} +			if (error && last_error != EFSCORRUPTED) +				last_error = error; +		} + +		mutex_unlock(&qi->qi_tree_lock); + +		/* bail out if the filesystem is corrupted.  */ +		if (last_error == EFSCORRUPTED) { +			skipped = 0; +			break; +		} +	} + +	if (skipped) { +		delay(1); +		goto restart; +	} + +	return last_error; +} + + +/* + * Purge a dquot from all tracking data structures and free it. + */ +STATIC int +xfs_qm_dqpurge( +	struct xfs_dquot	*dqp) +{ +	struct xfs_mount	*mp = dqp->q_mount; +	struct xfs_quotainfo	*qi = mp->m_quotainfo; +	struct xfs_dquot	*gdqp = NULL; + +	xfs_dqlock(dqp); +	if ((dqp->dq_flags & XFS_DQ_FREEING) || dqp->q_nrefs != 0) { +		xfs_dqunlock(dqp); +		return EAGAIN; +	} + +	/* +	 * If this quota has a group hint attached, prepare for releasing it +	 * now. +	 */ +	gdqp = dqp->q_gdquot; +	if (gdqp) { +		xfs_dqlock(gdqp); +		dqp->q_gdquot = NULL; +	} + +	dqp->dq_flags |= XFS_DQ_FREEING; + +	/* +	 * 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); + +	radix_tree_delete(XFS_DQUOT_TREE(qi, dqp->q_core.d_flags), +			  be32_to_cpu(dqp->q_core.d_id)); +	qi->qi_dquots--; + +	/* +	 * 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); + +	if (gdqp) +		xfs_qm_dqput(gdqp); +	return 0; +} + +/* + * Purge the dquot cache. + */ +void +xfs_qm_dqpurge_all( +	struct xfs_mount	*mp, +	uint			flags) +{ +	if (flags & XFS_QMOPT_UQUOTA) +		xfs_qm_dquot_walk(mp, XFS_DQ_USER, xfs_qm_dqpurge); +	if (flags & XFS_QMOPT_GQUOTA) +		xfs_qm_dquot_walk(mp, XFS_DQ_GROUP, xfs_qm_dqpurge); +	if (flags & XFS_QMOPT_PQUOTA) +		xfs_qm_dquot_walk(mp, XFS_DQ_PROJ, xfs_qm_dqpurge); +} + +/*   * Just destroy the quotainfo structure.   */  void @@ -306,175 +487,6 @@ xfs_qm_unmount_quotas(  	}  } -/* - * Flush all dquots of the given file system to disk. The dquots are - * _not_ purged from memory here, just their data written to disk. - */ -STATIC int -xfs_qm_dqflush_all( -	struct xfs_mount	*mp) -{ -	struct xfs_quotainfo	*q = mp->m_quotainfo; -	int			recl; -	struct xfs_dquot	*dqp; -	int			error; - -	if (!q) -		return 0; -again: -	mutex_lock(&q->qi_dqlist_lock); -	list_for_each_entry(dqp, &q->qi_dqlist, q_mplist) { -		xfs_dqlock(dqp); -		if ((dqp->dq_flags & XFS_DQ_FREEING) || -		    !XFS_DQ_IS_DIRTY(dqp)) { -			xfs_dqunlock(dqp); -			continue; -		} - -		/* XXX a sentinel would be better */ -		recl = q->qi_dqreclaims; -		if (!xfs_dqflock_nowait(dqp)) { -			/* -			 * If we can't grab the flush lock then check -			 * to see if the dquot has been flushed delayed -			 * write.  If so, grab its buffer and send it -			 * out immediately.  We'll be able to acquire -			 * the flush lock when the I/O completes. -			 */ -			xfs_dqflock_pushbuf_wait(dqp); -		} -		/* -		 * Let go of the mplist lock. We don't want to hold it -		 * across a disk write. -		 */ -		mutex_unlock(&q->qi_dqlist_lock); -		error = xfs_qm_dqflush(dqp, 0); -		xfs_dqunlock(dqp); -		if (error) -			return error; - -		mutex_lock(&q->qi_dqlist_lock); -		if (recl != q->qi_dqreclaims) { -			mutex_unlock(&q->qi_dqlist_lock); -			/* XXX restart limit */ -			goto again; -		} -	} - -	mutex_unlock(&q->qi_dqlist_lock); -	/* return ! busy */ -	return 0; -} - -/* - * Release the group dquot pointers the user dquots may be - * carrying around as a hint. mplist is locked on entry and exit. - */ -STATIC void -xfs_qm_detach_gdquots( -	struct xfs_mount	*mp) -{ -	struct xfs_quotainfo	*q = mp->m_quotainfo; -	struct xfs_dquot	*dqp, *gdqp; - - again: -	ASSERT(mutex_is_locked(&q->qi_dqlist_lock)); -	list_for_each_entry(dqp, &q->qi_dqlist, q_mplist) { -		xfs_dqlock(dqp); -		if (dqp->dq_flags & XFS_DQ_FREEING) { -			xfs_dqunlock(dqp); -			mutex_unlock(&q->qi_dqlist_lock); -			delay(1); -			mutex_lock(&q->qi_dqlist_lock); -			goto again; -		} - -		gdqp = dqp->q_gdquot; -		if (gdqp) -			dqp->q_gdquot = NULL; -		xfs_dqunlock(dqp); - -		if (gdqp) -			xfs_qm_dqrele(gdqp); -	} -} - -/* - * Go through all the incore dquots of this file system and take them - * off the mplist and hashlist, if the dquot type matches the dqtype - * parameter. This is used when turning off quota accounting for - * users and/or groups, as well as when the filesystem is unmounting. - */ -STATIC int -xfs_qm_dqpurge_int( -	struct xfs_mount	*mp, -	uint			flags) -{ -	struct xfs_quotainfo	*q = mp->m_quotainfo; -	struct xfs_dquot	*dqp, *n; -	uint			dqtype; -	int			nmisses = 0; -	LIST_HEAD		(dispose_list); - -	if (!q) -		return 0; - -	dqtype = (flags & XFS_QMOPT_UQUOTA) ? XFS_DQ_USER : 0; -	dqtype |= (flags & XFS_QMOPT_PQUOTA) ? XFS_DQ_PROJ : 0; -	dqtype |= (flags & XFS_QMOPT_GQUOTA) ? XFS_DQ_GROUP : 0; - -	mutex_lock(&q->qi_dqlist_lock); - -	/* -	 * In the first pass through all incore dquots of this filesystem, -	 * we release the group dquot pointers the user dquots may be -	 * carrying around as a hint. We need to do this irrespective of -	 * what's being turned off. -	 */ -	xfs_qm_detach_gdquots(mp); - -	/* -	 * Try to get rid of all of the unwanted dquots. -	 */ -	list_for_each_entry_safe(dqp, n, &q->qi_dqlist, q_mplist) { -		xfs_dqlock(dqp); -		if ((dqp->dq_flags & dqtype) != 0 && -		    !(dqp->dq_flags & XFS_DQ_FREEING)) { -			if (dqp->q_nrefs == 0) { -				dqp->dq_flags |= XFS_DQ_FREEING; -				list_move_tail(&dqp->q_mplist, &dispose_list); -			} else -				nmisses++; -		} -		xfs_dqunlock(dqp); -	} -	mutex_unlock(&q->qi_dqlist_lock); - -	list_for_each_entry_safe(dqp, n, &dispose_list, q_mplist) -		xfs_qm_dqpurge(dqp); - -	return nmisses; -} - -int -xfs_qm_dqpurge_all( -	xfs_mount_t	*mp, -	uint		flags) -{ -	int		ndquots; - -	/* -	 * Purge the dquot cache. -	 * None of the dquots should really be busy at this point. -	 */ -	if (mp->m_quotainfo) { -		while ((ndquots = xfs_qm_dqpurge_int(mp, flags))) { -			delay(ndquots * 10); -		} -	} -	return 0; -} -  STATIC int  xfs_qm_dqattach_one(  	xfs_inode_t	*ip, @@ -749,15 +761,10 @@ xfs_qm_init_quotainfo(  	INIT_RADIX_TREE(&qinf->qi_gquota_tree, GFP_NOFS);  	mutex_init(&qinf->qi_tree_lock); -	INIT_LIST_HEAD(&qinf->qi_dqlist); -	mutex_init(&qinf->qi_dqlist_lock); -  	INIT_LIST_HEAD(&qinf->qi_lru_list);  	qinf->qi_lru_count = 0;  	mutex_init(&qinf->qi_lru_lock); -	qinf->qi_dqreclaims = 0; -  	/* mutex used to serialize quotaoffs */  	mutex_init(&qinf->qi_quotaofflock); @@ -854,9 +861,6 @@ xfs_qm_destroy_quotainfo(  	 */  	xfs_qm_rele_quotafs_ref(mp); -	ASSERT(list_empty(&qi->qi_dqlist)); -	mutex_destroy(&qi->qi_dqlist_lock); -  	if (qi->qi_uquotaip) {  		IRELE(qi->qi_uquotaip);  		qi->qi_uquotaip = NULL; /* paranoia */ @@ -1307,6 +1311,28 @@ error0:  	return error;  } +STATIC int +xfs_qm_flush_one( +	struct xfs_dquot	*dqp) +{ +	int			error = 0; + +	xfs_dqlock(dqp); +	if (dqp->dq_flags & XFS_DQ_FREEING) +		goto out_unlock; +	if (!XFS_DQ_IS_DIRTY(dqp)) +		goto out_unlock; + +	if (!xfs_dqflock_nowait(dqp)) +		xfs_dqflock_pushbuf_wait(dqp); + +	error = xfs_qm_dqflush(dqp, 0); + +out_unlock: +	xfs_dqunlock(dqp); +	return error; +} +  /*   * Walk thru all the filesystem inodes and construct a consistent view   * of the disk quota world. If the quotacheck fails, disable quotas. @@ -1315,7 +1341,7 @@ int  xfs_qm_quotacheck(  	xfs_mount_t	*mp)  { -	int		done, count, error; +	int		done, count, error, error2;  	xfs_ino_t	lastino;  	size_t		structsz;  	xfs_inode_t	*uip, *gip; @@ -1329,12 +1355,6 @@ xfs_qm_quotacheck(  	ASSERT(mp->m_quotainfo->qi_uquotaip || mp->m_quotainfo->qi_gquotaip);  	ASSERT(XFS_IS_QUOTA_RUNNING(mp)); -	/* -	 * There should be no cached dquots. The (simplistic) quotacheck -	 * algorithm doesn't like that. -	 */ -	ASSERT(list_empty(&mp->m_quotainfo->qi_dqlist)); -  	xfs_notice(mp, "Quotacheck needed: Please wait.");  	/* @@ -1373,12 +1393,21 @@ xfs_qm_quotacheck(  	} while (!done);  	/* -	 * We've made all the changes that we need to make incore. -	 * Flush them down to disk buffers if everything was updated -	 * successfully. +	 * We've made all the changes that we need to make incore.  Flush them +	 * down to disk buffers if everything was updated successfully.  	 */ -	if (!error) -		error = xfs_qm_dqflush_all(mp); +	if (XFS_IS_UQUOTA_ON(mp)) +		error = xfs_qm_dquot_walk(mp, XFS_DQ_USER, xfs_qm_flush_one); +	if (XFS_IS_GQUOTA_ON(mp)) { +		error2 = xfs_qm_dquot_walk(mp, XFS_DQ_GROUP, xfs_qm_flush_one); +		if (!error) +			error = error2; +	} +	if (XFS_IS_PQUOTA_ON(mp)) { +		error2 = xfs_qm_dquot_walk(mp, XFS_DQ_PROJ, xfs_qm_flush_one); +		if (!error) +			error = error2; +	}  	/*  	 * We can get this error if we couldn't do a dquot allocation inside @@ -1517,13 +1546,9 @@ xfs_qm_dqfree_one(  	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_dquots--; -	qi->qi_dqreclaims++; -	mutex_unlock(&qi->qi_dqlist_lock); +	mutex_unlock(&qi->qi_tree_lock);  	xfs_qm_dqdestroy(dqp);  } @@ -1556,8 +1581,6 @@ xfs_qm_dqreclaim_one(  		return;  	} -	ASSERT(!list_empty(&dqp->q_mplist)); -  	/*  	 * 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. diff --git a/fs/xfs/xfs_qm.h b/fs/xfs/xfs_qm.h index 8f4b117823cc..76447060cd47 100644 --- a/fs/xfs/xfs_qm.h +++ b/fs/xfs/xfs_qm.h @@ -63,11 +63,7 @@ typedef struct xfs_quotainfo {  	struct list_head qi_lru_list;  	struct mutex	 qi_lru_lock;  	int		 qi_lru_count; -	struct list_head qi_dqlist;	 /* all dquots in filesys */ -	struct mutex	 qi_dqlist_lock;  	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_itimelimit;	 /* limit for inodes timer */  	time_t		 qi_rtbtimelimit;/* limit for rt blks timer */ @@ -126,7 +122,7 @@ extern int		xfs_qm_quotacheck(xfs_mount_t *);  extern int		xfs_qm_write_sb_changes(xfs_mount_t *, __int64_t);  /* 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);  /* quota ops */ diff --git a/fs/xfs/xfs_qm_syscalls.c b/fs/xfs/xfs_qm_syscalls.c index b9ac268a2d7c..c4f396e437a8 100644 --- a/fs/xfs/xfs_qm_syscalls.c +++ b/fs/xfs/xfs_qm_syscalls.c @@ -66,7 +66,6 @@ xfs_qm_scall_quotaoff(  	int			error;  	uint			inactivate_flags;  	xfs_qoff_logitem_t	*qoffstart; -	int			nculprits;  	/*  	 * No file system can have quotas enabled on disk but not in core. @@ -172,18 +171,13 @@ xfs_qm_scall_quotaoff(  	 * 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.  	 */ -	mp->m_qflags &= ~(flags); +	mp->m_qflags &= ~flags;  	/*  	 * 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 -	 * 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. +	 * according to what was turned off.  	 */ -	while ((nculprits = xfs_qm_dqpurge_all(mp, dqtype))) -		delay(10 * nculprits); +	xfs_qm_dqpurge_all(mp, dqtype);  	/*  	 * Transactions that had started before ACTIVE state bit was cleared |