aboutsummaryrefslogtreecommitdiff
path: root/sys/kern/vfs_syscalls.c
diff options
context:
space:
mode:
Diffstat (limited to 'sys/kern/vfs_syscalls.c')
-rw-r--r--sys/kern/vfs_syscalls.c19
1 files changed, 9 insertions, 10 deletions
diff --git a/sys/kern/vfs_syscalls.c b/sys/kern/vfs_syscalls.c
index 55780b0474ee..2f4a6036ef88 100644
--- a/sys/kern/vfs_syscalls.c
+++ b/sys/kern/vfs_syscalls.c
@@ -89,8 +89,6 @@ __FBSDID("$FreeBSD$");
#include <fs/devfs/devfs.h>
-#include <ufs/ufs/quota.h>
-
MALLOC_DEFINE(M_FADVISE, "fadvise", "posix_fadvise(2) information");
static int kern_chflagsat(struct thread *td, int fd, const char *path,
@@ -195,6 +193,7 @@ sys_quotactl(struct thread *td, struct quotactl_args *uap)
struct mount *mp;
struct nameidata nd;
int error;
+ bool mp_busy;
AUDIT_ARG_CMD(uap->cmd);
AUDIT_ARG_UID(uap->uid);
@@ -213,21 +212,21 @@ sys_quotactl(struct thread *td, struct quotactl_args *uap)
vfs_rel(mp);
return (error);
}
- error = VFS_QUOTACTL(mp, uap->cmd, uap->uid, uap->arg);
+ mp_busy = true;
+ error = VFS_QUOTACTL(mp, uap->cmd, uap->uid, uap->arg, &mp_busy);
/*
- * Since quota on operation typically needs to open quota
- * file, the Q_QUOTAON handler needs to unbusy the mount point
+ * Since quota on/off operations typically need to open quota
+ * files, the implementation may need to unbusy the mount point
* before calling into namei. Otherwise, unmount might be
- * started between two vfs_busy() invocations (first is our,
+ * started between two vfs_busy() invocations (first is ours,
* second is from mount point cross-walk code in lookup()),
* causing deadlock.
*
- * Require that Q_QUOTAON handles the vfs_busy() reference on
- * its own, always returning with ubusied mount point.
+ * Avoid unbusying mp if the implementation indicates it has
+ * already done so.
*/
- if ((uap->cmd >> SUBCMDSHIFT) != Q_QUOTAON &&
- (uap->cmd >> SUBCMDSHIFT) != Q_QUOTAOFF)
+ if (mp_busy)
vfs_unbusy(mp);
vfs_rel(mp);
return (error);