diff options
Diffstat (limited to 'sys/ufs/ufs/ufs_quota.c')
-rw-r--r-- | sys/ufs/ufs/ufs_quota.c | 23 |
1 files changed, 16 insertions, 7 deletions
diff --git a/sys/ufs/ufs/ufs_quota.c b/sys/ufs/ufs/ufs_quota.c index 87ac9a1..a949898 100644 --- a/sys/ufs/ufs/ufs_quota.c +++ b/sys/ufs/ufs/ufs_quota.c @@ -80,7 +80,7 @@ static int dqopen(struct vnode *, struct ufsmount *, int); static int dqget(struct vnode *, u_long, struct ufsmount *, int, struct dquot **); static int dqsync(struct vnode *, struct dquot *); -static void dqflush(struct vnode *); +static int dqflush(struct vnode *); static int quotaoff1(struct thread *td, struct mount *mp, int type); static int quotaoff_inchange(struct thread *td, struct mount *mp, int type); @@ -674,8 +674,12 @@ again: vrele(vp); } - dqflush(qvp); - /* Clear um_quotas before closing the quota vnode to prevent + error = dqflush(qvp); + if (error != 0) + return (error); + + /* + * Clear um_quotas before closing the quota vnode to prevent * access to the closed vnode from dqget/dqsync */ UFS_LOCK(ump); @@ -1594,17 +1598,19 @@ out: /* * Flush all entries from the cache for a particular vnode. */ -static void +static int dqflush(struct vnode *vp) { struct dquot *dq, *nextdq; struct dqhash *dqh; + int error; /* * Move all dquot's that used to refer to this quota * file off their hash chains (they will eventually * fall off the head of the free list and be re-used). */ + error = 0; DQH_LOCK(); for (dqh = &dqhashtbl[dqhash]; dqh >= dqhashtbl; dqh--) { for (dq = LIST_FIRST(dqh); dq; dq = nextdq) { @@ -1612,12 +1618,15 @@ dqflush(struct vnode *vp) if (dq->dq_ump->um_quotas[dq->dq_type] != vp) continue; if (dq->dq_cnt) - panic("dqflush: stray dquot"); - LIST_REMOVE(dq, dq_hash); - dq->dq_ump = (struct ufsmount *)0; + error = EBUSY; + else { + LIST_REMOVE(dq, dq_hash); + dq->dq_ump = NULL; + } } } DQH_UNLOCK(); + return (error); } /* |