svn commit: r338733 - head/sys/ufs/ufs
Konstantin Belousov
kib at FreeBSD.org
Mon Sep 17 19:38:44 UTC 2018
Author: kib
Date: Mon Sep 17 19:38:43 2018
New Revision: 338733
URL: https://svnweb.freebsd.org/changeset/base/338733
Log:
Do not upgrade the vnode lock to call getinoquota().
Doing so can deadlock when the thread already owns another vnode lock,
e.g. during a rename, as was demonstrated by the reporter. In fact,
there seems to be no need to force the call to getinoquota() always,
because vn_open() locks vnode exclusively, and this is the most
important case. To add to the point, directories where the dirent is
added or removed, are locked exclusively as well.
Reported by: bwidawsk
Tested by: bwidawsk, pho (as part of the larger patch)
Sponsored by: The FreeBSD Foundation
Approved by: re (gjb)
MFC after: 1 week
Modified:
head/sys/ufs/ufs/ufs_vnops.c
Modified: head/sys/ufs/ufs/ufs_vnops.c
==============================================================================
--- head/sys/ufs/ufs/ufs_vnops.c Mon Sep 17 19:20:50 2018 (r338732)
+++ head/sys/ufs/ufs/ufs_vnops.c Mon Sep 17 19:38:43 2018 (r338733)
@@ -325,9 +325,6 @@ ufs_accessx(ap)
struct inode *ip = VTOI(vp);
accmode_t accmode = ap->a_accmode;
int error;
-#ifdef QUOTA
- int relocked;
-#endif
#ifdef UFS_ACL
struct acl *acl;
acl_type_t type;
@@ -350,32 +347,14 @@ ufs_accessx(ap)
* Inode is accounted in the quotas only if struct
* dquot is attached to it. VOP_ACCESS() is called
* from vn_open_cred() and provides a convenient
- * point to call getinoquota().
+ * point to call getinoquota(). The lock mode is
+ * exclusive when the file is opening for write.
*/
- if (VOP_ISLOCKED(vp) != LK_EXCLUSIVE) {
-
- /*
- * Upgrade vnode lock, since getinoquota()
- * requires exclusive lock to modify inode.
- */
- relocked = 1;
- vhold(vp);
- vn_lock(vp, LK_UPGRADE | LK_RETRY);
- VI_LOCK(vp);
- if (vp->v_iflag & VI_DOOMED) {
- vdropl(vp);
- error = ENOENT;
- goto relock;
- }
- vdropl(vp);
- } else
- relocked = 0;
- error = getinoquota(ip);
-relock:
- if (relocked)
- vn_lock(vp, LK_DOWNGRADE | LK_RETRY);
- if (error != 0)
- return (error);
+ if (VOP_ISLOCKED(vp) == LK_EXCLUSIVE) {
+ error = getinoquota(ip);
+ if (error != 0)
+ return (error);
+ }
#endif
break;
default:
More information about the svn-src-head
mailing list