aboutsummaryrefslogtreecommitdiff
path: root/sys/kern
diff options
context:
space:
mode:
Diffstat (limited to 'sys/kern')
-rw-r--r--sys/kern/vfs_default.c4
-rw-r--r--sys/kern/vfs_init.c6
-rw-r--r--sys/kern/vfs_syscalls.c19
3 files changed, 15 insertions, 14 deletions
diff --git a/sys/kern/vfs_default.c b/sys/kern/vfs_default.c
index ace9ad1d37c3..63bca7810847 100644
--- a/sys/kern/vfs_default.c
+++ b/sys/kern/vfs_default.c
@@ -1350,13 +1350,13 @@ vfs_stdstatfs (mp, sbp)
}
int
-vfs_stdquotactl (mp, cmds, uid, arg)
+vfs_stdquotactl (mp, cmds, uid, arg, mp_busy)
struct mount *mp;
int cmds;
uid_t uid;
void *arg;
+ bool *mp_busy;
{
-
return (EOPNOTSUPP);
}
diff --git a/sys/kern/vfs_init.c b/sys/kern/vfs_init.c
index 3365ddb11474..112b4c76e575 100644
--- a/sys/kern/vfs_init.c
+++ b/sys/kern/vfs_init.c
@@ -212,12 +212,14 @@ vfs_cachedroot_sigdefer(struct mount *mp, int flags, struct vnode **vpp)
}
static int
-vfs_quotactl_sigdefer(struct mount *mp, int cmd, uid_t uid, void *arg)
+vfs_quotactl_sigdefer(struct mount *mp, int cmd, uid_t uid, void *arg,
+ bool *mp_busy)
{
int prev_stops, rc;
prev_stops = sigdeferstop(SIGDEFERSTOP_SILENT);
- rc = (*mp->mnt_vfc->vfc_vfsops_sd->vfs_quotactl)(mp, cmd, uid, arg);
+ rc = (*mp->mnt_vfc->vfc_vfsops_sd->vfs_quotactl)(mp, cmd, uid, arg,
+ mp_busy);
sigallowstop(prev_stops);
return (rc);
}
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);