diff options
Diffstat (limited to 'sys/kern')
-rw-r--r-- | sys/kern/vfs_default.c | 4 | ||||
-rw-r--r-- | sys/kern/vfs_init.c | 6 | ||||
-rw-r--r-- | sys/kern/vfs_syscalls.c | 19 |
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); |