Skip site navigation (1)Skip section navigation (2)
Date:      Sun, 20 Jun 2010 13:35:16 +0000 (UTC)
From:      Konstantin Belousov <kib@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org
Subject:   svn commit: r209367 - head/sys/ufs/ufs
Message-ID:  <201006201335.o5KDZG6O017206@svn.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: kib
Date: Sun Jun 20 13:35:16 2010
New Revision: 209367
URL: http://svn.freebsd.org/changeset/base/209367

Log:
  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

Modified:
  head/sys/ufs/ufs/ufs_lookup.c

Modified: head/sys/ufs/ufs/ufs_lookup.c
==============================================================================
--- head/sys/ufs/ufs/ufs_lookup.c	Sun Jun 20 12:52:33 2010	(r209366)
+++ head/sys/ufs/ufs/ufs_lookup.c	Sun Jun 20 13:35:16 2010	(r209367)
@@ -77,6 +77,32 @@ SYSCTL_INT(_debug, OID_AUTO, dircheck, C
 /* 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_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;



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201006201335.o5KDZG6O017206>