diff options
author | kib <kib@FreeBSD.org> | 2008-08-24 17:24:22 +0000 |
---|---|---|
committer | kib <kib@FreeBSD.org> | 2008-08-24 17:24:22 +0000 |
commit | 1eb6d5f22fc674a86f2fa61e6a52a4024e0a3ce8 (patch) | |
tree | d72ea907602193092db5fadeef13505468b7be34 /sys/ufs | |
parent | b170b03c8e7fb45f3b165ca67ee19e55f3ae9b53 (diff) | |
download | FreeBSD-src-1eb6d5f22fc674a86f2fa61e6a52a4024e0a3ce8.zip FreeBSD-src-1eb6d5f22fc674a86f2fa61e6a52a4024e0a3ce8.tar.gz |
Revert the r167541: "Remove unneeded getinoquota() call in the
ufs_access()." The call to getinoquota in ufs_access() serves the
purpose of instantiating inode dquot from the vn_open(). Since quotas
are accounted only for the inodes with already attached dquot, removal
of the call prevented opened inodes from participation in the quota
calculations.
Since ufs_access() may be called with the vnode being only shared
locked, upgrade (and then downgrade) vnode lock if calling
getinoquota().
Reported by: simon at optinet com
In collaboration with: pho
MFC after: 1 week
Diffstat (limited to 'sys/ufs')
-rw-r--r-- | sys/ufs/ufs/ufs_vnops.c | 24 |
1 files changed, 23 insertions, 1 deletions
diff --git a/sys/ufs/ufs/ufs_vnops.c b/sys/ufs/ufs/ufs_vnops.c index 5028975..850cb04 100644 --- a/sys/ufs/ufs/ufs_vnops.c +++ b/sys/ufs/ufs/ufs_vnops.c @@ -309,7 +309,7 @@ ufs_access(ap) struct vnode *vp = ap->a_vp; struct inode *ip = VTOI(vp); mode_t mode = ap->a_mode; - int error; + int error, relocked; #ifdef UFS_ACL struct acl *acl; #endif @@ -326,6 +326,28 @@ ufs_access(ap) case VREG: if (vp->v_mount->mnt_flag & MNT_RDONLY) return (EROFS); +#ifdef QUOTA + if (VOP_ISLOCKED(vp) != LK_EXCLUSIVE) { + relocked = 1; + vhold(vp); + vn_lock(vp, LK_UPGRADE | LK_RETRY); + VI_LOCK(vp); + vdropl(vp); + if (vp->v_iflag & VI_DOOMED) { + VI_UNLOCK(vp); + error = ENOENT; + goto relock; + } + VI_UNLOCK(vp); + } else + relocked = 0; + error = getinoquota(ip); +relock: + if (relocked) + vn_lock(vp, LK_DOWNGRADE | LK_RETRY); + if (error != 0) + return (error); +#endif break; default: break; |