Page Menu
Home
FreeBSD
Search
Configure Global Search
Log In
Files
F140560476
D30218.id89382.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Flag For Later
Award Token
Size
12 KB
Referenced Files
None
Subscribers
None
D30218.id89382.diff
View Options
Index: share/man/man9/VFS_QUOTACTL.9
===================================================================
--- share/man/man9/VFS_QUOTACTL.9
+++ share/man/man9/VFS_QUOTACTL.9
@@ -28,7 +28,7 @@
.\"
.\" $FreeBSD$
.\"
-.Dd December 17, 2020
+.Dd May 11, 2021
.Dt VFS_QUOTACTL 9
.Os
.Sh NAME
@@ -39,12 +39,38 @@
.In sys/mount.h
.In sys/vnode.h
.Ft int
-.Fn VFS_QUOTACTL "struct mount *mp" "int cmds" "uid_t uid" "void *arg"
+.Fn VFS_QUOTACTL "struct mount *mp" "int cmds" "uid_t uid" "void *arg" "bool *mp_busy"
.Sh DESCRIPTION
Implement file system quotas.
+.Pp
+The
+.Fa mp_busy
+argument is an input/output parameter.
+.Fn VFS_QUOTACTL
+must be called with
+.Fa mp
+marked busy through
+.Xr vfs_busy 9
+and
+.Fa *mp_busy
+set to true.
+The filesystem implementation of
+.Fn VFS_QUOTACTL
+may then unbusy
+.Fa mp
+using
+.Xr vfs_unbusy 9
+prior to performing quota file I/O.
+In this case the implementation must set
+.Fa *mp_busy
+to false to indicate that the caller must not unbusy
+.Fa mp
+upon completion of
+.Fn VFS_QUOTACTL .
+.Pp
See
.Xr quotactl 2
-for a description of the arguments.
+for a description of the remaining arguments.
.Sh SEE ALSO
.Xr quotactl 2 ,
.Xr vnode 9
Index: sys/contrib/openzfs/module/os/freebsd/zfs/zfs_vfsops.c
===================================================================
--- sys/contrib/openzfs/module/os/freebsd/zfs/zfs_vfsops.c
+++ sys/contrib/openzfs/module/os/freebsd/zfs/zfs_vfsops.c
@@ -102,7 +102,12 @@
"ZPL_VERSION");
/* END CSTYLED */
+#if __FreeBSD_version >= 1400014
+static int zfs_quotactl(vfs_t *vfsp, int cmds, uid_t id, void *arg,
+ bool *mp_busy);
+#else
static int zfs_quotactl(vfs_t *vfsp, int cmds, uid_t id, void *arg);
+#endif
static int zfs_mount(vfs_t *vfsp);
static int zfs_umount(vfs_t *vfsp, int fflag);
static int zfs_root(vfs_t *vfsp, int flags, vnode_t **vpp);
@@ -267,7 +272,11 @@
}
static int
+#if __FreeBSD_version >= 1400014
+zfs_quotactl(vfs_t *vfsp, int cmds, uid_t id, void *arg, bool *mp_busy)
+#else
zfs_quotactl(vfs_t *vfsp, int cmds, uid_t id, void *arg)
+#endif
{
zfsvfs_t *zfsvfs = vfsp->vfs_data;
struct thread *td;
@@ -291,8 +300,10 @@
break;
default:
error = EINVAL;
+#if __FreeBSD_version < 1400014
if (cmd == Q_QUOTAON || cmd == Q_QUOTAOFF)
vfs_unbusy(vfsp);
+#endif
goto done;
}
}
@@ -351,11 +362,15 @@
case Q_QUOTAON:
// As far as I can tell, you can't turn quotas on or off on zfs
error = 0;
+#if __FreeBSD_version < 1400014
vfs_unbusy(vfsp);
+#endif
break;
case Q_QUOTAOFF:
error = ENOTSUP;
+#if __FreeBSD_version < 1400014
vfs_unbusy(vfsp);
+#endif
break;
case Q_SETQUOTA:
error = copyin(arg, &dqblk, sizeof (dqblk));
Index: sys/fs/nullfs/null_vfsops.c
===================================================================
--- sys/fs/nullfs/null_vfsops.c
+++ sys/fs/nullfs/null_vfsops.c
@@ -294,13 +294,30 @@
}
static int
-nullfs_quotactl(mp, cmd, uid, arg)
+nullfs_quotactl(mp, cmd, uid, arg, mp_busy)
struct mount *mp;
int cmd;
uid_t uid;
void *arg;
+ bool *mp_busy;
{
- return VFS_QUOTACTL(MOUNTTONULLMOUNT(mp)->nullm_vfs, cmd, uid, arg);
+ struct null_mount *mntdata;
+ int error;
+ bool unbusy;
+
+ mntdata = MOUNTTONULLMOUNT(mp);
+ unbusy = true;
+
+ error = vfs_busy(mntdata->nullm_vfs, MBF_NOWAIT);
+ if (error != 0)
+ return (error);
+
+ error = VFS_QUOTACTL(mntdata->nullm_vfs, cmd, uid, arg, &unbusy);
+
+ if (unbusy)
+ vfs_unbusy(mntdata->nullm_vfs);
+
+ return (error);
}
static int
Index: sys/fs/smbfs/smbfs_vfsops.c
===================================================================
--- sys/fs/smbfs/smbfs_vfsops.c
+++ sys/fs/smbfs/smbfs_vfsops.c
@@ -352,11 +352,12 @@
*/
/* ARGSUSED */
static int
-smbfs_quotactl(mp, cmd, uid, arg)
+smbfs_quotactl(mp, cmd, uid, arg, mp_busy)
struct mount *mp;
int cmd;
uid_t uid;
void *arg;
+ bool *mp_busy;
{
SMBVDEBUG("return EOPNOTSUPP\n");
return EOPNOTSUPP;
Index: sys/fs/unionfs/union_vfsops.c
===================================================================
--- sys/fs/unionfs/union_vfsops.c
+++ sys/fs/unionfs/union_vfsops.c
@@ -371,16 +371,30 @@
}
static int
-unionfs_quotactl(struct mount *mp, int cmd, uid_t uid, void *arg)
+unionfs_quotactl(struct mount *mp, int cmd, uid_t uid, void *arg,
+ bool *mp_busy)
{
struct unionfs_mount *ump;
+ int error;
+ bool unbusy;
+ unbusy = true;
ump = MOUNTTOUNIONFSMOUNT(mp);
+ error = vfs_busy(ump->um_uppervp->v_mount, MBF_NOWAIT);
+ if (error != 0)
+ return (error);
+
/*
* Writing is always performed to upper vnode.
*/
- return (VFS_QUOTACTL(ump->um_uppervp->v_mount, cmd, uid, arg));
+ error = VFS_QUOTACTL(ump->um_uppervp->v_mount, cmd, uid, arg,
+ &unbusy);
+
+ if (unbusy)
+ vfs_unbusy(ump->um_uppervp->v_mount);
+
+ return (error);
}
static int
Index: sys/kern/vfs_default.c
===================================================================
--- sys/kern/vfs_default.c
+++ sys/kern/vfs_default.c
@@ -1322,13 +1322,13 @@
}
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);
}
Index: sys/kern/vfs_init.c
===================================================================
--- sys/kern/vfs_init.c
+++ sys/kern/vfs_init.c
@@ -212,12 +212,14 @@
}
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);
}
Index: sys/kern/vfs_syscalls.c
===================================================================
--- sys/kern/vfs_syscalls.c
+++ sys/kern/vfs_syscalls.c
@@ -89,8 +89,6 @@
#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 @@
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 @@
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);
Index: sys/sys/mount.h
===================================================================
--- sys/sys/mount.h
+++ sys/sys/mount.h
@@ -760,7 +760,8 @@
typedef int vfs_cmount_t(struct mntarg *ma, void *data, uint64_t flags);
typedef int vfs_unmount_t(struct mount *mp, int mntflags);
typedef int vfs_root_t(struct mount *mp, int flags, struct vnode **vpp);
-typedef int vfs_quotactl_t(struct mount *mp, int cmds, uid_t uid, void *arg);
+typedef int vfs_quotactl_t(struct mount *mp, int cmds, uid_t uid, void *arg,
+ bool *mp_busy);
typedef int vfs_statfs_t(struct mount *mp, struct statfs *sbp);
typedef int vfs_sync_t(struct mount *mp, int waitfor);
typedef int vfs_vget_t(struct mount *mp, ino_t ino, int flags,
@@ -833,10 +834,10 @@
_rc = (*(MP)->mnt_op->vfs_cachedroot)(MP, FLAGS, VPP); \
_rc; })
-#define VFS_QUOTACTL(MP, C, U, A) ({ \
+#define VFS_QUOTACTL(MP, C, U, A, MP_BUSY) ({ \
int _rc; \
\
- _rc = (*(MP)->mnt_op->vfs_quotactl)(MP, C, U, A); \
+ _rc = (*(MP)->mnt_op->vfs_quotactl)(MP, C, U, A, MP_BUSY); \
_rc; })
#define VFS_STATFS(MP, SBP) ({ \
Index: sys/sys/param.h
===================================================================
--- sys/sys/param.h
+++ sys/sys/param.h
@@ -76,7 +76,7 @@
* cannot include sys/param.h and should only be updated here.
*/
#undef __FreeBSD_version
-#define __FreeBSD_version 1400013
+#define __FreeBSD_version 1400014
/*
* __FreeBSD_kernel__ indicates that this system uses the kernel of FreeBSD,
Index: sys/ufs/ufs/quota.h
===================================================================
--- sys/ufs/ufs/quota.h
+++ sys/ufs/ufs/quota.h
@@ -232,7 +232,7 @@
int qsync(struct mount *);
int qsyncvp(struct vnode *);
int quotaoff(struct thread *, struct mount *, int);
-int quotaon(struct thread *, struct mount *, int, void *);
+int quotaon(struct thread *, struct mount *, int, void *, bool *);
int getquota32(struct thread *, struct mount *, u_long, int, void *);
int setquota32(struct thread *, struct mount *, u_long, int, void *);
int setuse32(struct thread *, struct mount *, u_long, int, void *);
Index: sys/ufs/ufs/ufs_quota.c
===================================================================
--- sys/ufs/ufs/ufs_quota.c
+++ sys/ufs/ufs/ufs_quota.c
@@ -492,7 +492,8 @@
* Q_QUOTAON - set up a quota file for a particular filesystem.
*/
int
-quotaon(struct thread *td, struct mount *mp, int type, void *fname)
+quotaon(struct thread *td, struct mount *mp, int type, void *fname,
+ bool *mp_busy)
{
struct ufsmount *ump;
struct vnode *vp, **vpp;
@@ -502,15 +503,11 @@
struct nameidata nd;
error = priv_check(td, PRIV_UFS_QUOTAON);
- if (error != 0) {
- vfs_unbusy(mp);
+ if (error != 0)
return (error);
- }
- if ((mp->mnt_flag & MNT_RDONLY) != 0) {
- vfs_unbusy(mp);
+ if ((mp->mnt_flag & MNT_RDONLY) != 0)
return (EROFS);
- }
ump = VFSTOUFS(mp);
dq = NODQUOT;
@@ -518,7 +515,9 @@
NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, fname, td);
flags = FREAD | FWRITE;
vfs_ref(mp);
+ KASSERT(*mp_busy, ("%s called without busied mount", __func__));
vfs_unbusy(mp);
+ *mp_busy = false;
error = vn_open(&nd, &flags, 0, NULL);
if (error != 0) {
vfs_rel(mp);
@@ -529,10 +528,9 @@
error = vfs_busy(mp, MBF_NOWAIT);
vfs_rel(mp);
if (error == 0) {
- if (vp->v_type != VREG) {
+ *mp_busy = true;
+ if (vp->v_type != VREG)
error = EACCES;
- vfs_unbusy(mp);
- }
}
if (error != 0) {
VOP_UNLOCK(vp);
@@ -545,7 +543,6 @@
UFS_UNLOCK(ump);
VOP_UNLOCK(vp);
(void) vn_close(vp, FREAD|FWRITE, td->td_ucred, td);
- vfs_unbusy(mp);
return (EALREADY);
}
ump->um_qflags[type] |= QTF_OPENING|QTF_CLOSING;
@@ -556,7 +553,6 @@
ump->um_qflags[type] &= ~(QTF_OPENING|QTF_CLOSING);
UFS_UNLOCK(ump);
(void) vn_close(vp, FREAD|FWRITE, td->td_ucred, td);
- vfs_unbusy(mp);
return (error);
}
VOP_UNLOCK(vp);
@@ -640,7 +636,6 @@
("quotaon: leaking flags"));
UFS_UNLOCK(ump);
- vfs_unbusy(mp);
return (error);
}
Index: sys/ufs/ufs/ufs_vfsops.c
===================================================================
--- sys/ufs/ufs/ufs_vfsops.c
+++ sys/ufs/ufs/ufs_vfsops.c
@@ -87,17 +87,14 @@
* Do operations associated with quotas
*/
int
-ufs_quotactl(mp, cmds, id, arg)
+ufs_quotactl(mp, cmds, id, arg, mp_busy)
struct mount *mp;
int cmds;
uid_t id;
void *arg;
+ bool *mp_busy;
{
#ifndef QUOTA
- if ((cmds >> SUBCMDSHIFT) == Q_QUOTAON ||
- (cmds >> SUBCMDSHIFT) == Q_QUOTAOFF)
- vfs_unbusy(mp);
-
return (EOPNOTSUPP);
#else
struct thread *td;
@@ -117,25 +114,23 @@
break;
default:
- if (cmd == Q_QUOTAON || cmd == Q_QUOTAOFF)
- vfs_unbusy(mp);
return (EINVAL);
}
}
- if ((u_int)type >= MAXQUOTAS) {
- if (cmd == Q_QUOTAON || cmd == Q_QUOTAOFF)
- vfs_unbusy(mp);
+ if ((u_int)type >= MAXQUOTAS)
return (EINVAL);
- }
switch (cmd) {
case Q_QUOTAON:
- error = quotaon(td, mp, type, arg);
+ error = quotaon(td, mp, type, arg, mp_busy);
break;
case Q_QUOTAOFF:
vfs_ref(mp);
+ KASSERT(*mp_busy,
+ ("%s called without busied mount", __func__));
vfs_unbusy(mp);
+ *mp_busy = false;
vn_start_write(NULL, &mp, V_WAIT | V_MNTREF);
error = quotaoff(td, mp, type);
vn_finished_write(mp);
File Metadata
Details
Attached
Mime Type
text/plain
Expires
Fri, Dec 26, 7:01 AM (17 h, 25 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
27277577
Default Alt Text
D30218.id89382.diff (12 KB)
Attached To
Mode
D30218: VFS_QUOTACTL(9): allow implementation to indicate busy state changes
Attached
Detach File
Event Timeline
Log In to Comment