Ensure that VOP_ACCESSX is called with exclusively locked vnode for

the kernel compiled with QUOTA option. ufs_accessx() upgrades the vdp
vnode lock from shared to exclusive to assign the dquot structure to
the vnode, and ufs_delete_denied() is called when tvp is locked. Since
upgrade drops shared lock when non-blocked upgrade failed, LOR is there.

Reported and tested by:	Dmitry Pryanishnikov <lynx.ripe gmail com>
Tested by:	pho
PR:	kern/147890
MFC after:	1 week
This commit is contained in:
Konstantin Belousov 2010-06-20 13:35:16 +00:00
parent fafb8f11c0
commit 427ef27ec7

View File

@ -77,6 +77,32 @@ SYSCTL_INT(_debug, OID_AUTO, dircheck, CTLFLAG_RW, &dirchk, 0, "");
/* true if old FS format...*/
#define OFSFMT(vp) ((vp)->v_mount->mnt_maxsymlinklen <= 0)
#ifdef QUOTA
static int
ufs_lookup_upgrade_lock(struct vnode *vp)
{
int error;
ASSERT_VOP_LOCKED(vp, __FUNCTION__);
if (VOP_ISLOCKED(vp) == LK_EXCLUSIVE)
return (0);
error = 0;
/*
* Upgrade vnode lock, since getinoquota()
* requires exclusive lock to modify inode.
*/
vhold(vp);
vn_lock(vp, LK_UPGRADE | LK_RETRY);
VI_LOCK(vp);
if (vp->v_iflag & VI_DOOMED)
error = ENOENT;
vdropl(vp);
return (error);
}
#endif
static int
ufs_delete_denied(struct vnode *vdp, struct vnode *tdp, struct ucred *cred,
struct thread *td)
@ -232,6 +258,13 @@ ufs_lookup_ino(struct vnode *vdp, struct vnode **vpp, struct componentname *cnp,
vnode_create_vobject(vdp, DIP(dp, i_size), cnp->cn_thread);
bmask = VFSTOUFS(vdp->v_mount)->um_mountp->mnt_stat.f_iosize - 1;
#ifdef QUOTA
if ((nameiop == DELETE || nameiop == RENAME) && (flags & ISLASTCN)) {
error = ufs_lookup_upgrade_lock(vdp);
if (error != 0)
return (error);
}
#endif
restart:
bp = NULL;