aboutsummaryrefslogtreecommitdiff
path: root/sys/kern/vfs_init.c
diff options
context:
space:
mode:
authorKonstantin Belousov <kib@FreeBSD.org>2018-10-23 21:43:41 +0000
committerKonstantin Belousov <kib@FreeBSD.org>2018-10-23 21:43:41 +0000
commit8ff7fad1d70ef7c6c43e1dd688ba1747c81077dd (patch)
treee24dfb24d4701daf71931772d10ea92583b77dcb /sys/kern/vfs_init.c
parentec888383cff48d90ac65cdbcad1e3f8e152ff8ca (diff)
downloadsrc-8ff7fad1d70ef7c6c43e1dd688ba1747c81077dd.tar.gz
src-8ff7fad1d70ef7c6c43e1dd688ba1747c81077dd.zip
Only call sigdeferstop() for NFS.
Use bypass to catch any NFS VOP dispatch and route it through the wrapper which does sigdeferstop() and then dispatches original VOP. NFS does not need a bypass below it, which is not supported. The vop offset in the vop_vector is added since otherwise it is impossible to get vop_op_t from the internal table, and I did not wanted to create the layered fs only to wrap NFS VOPs. VFS_OP()s wrap is straightforward. Requested and reviewed by: mjg (previous version) Tested by: pho Sponsored by: The FreeBSD Foundation Differential revision: https://reviews.freebsd.org/D17658
Notes
Notes: svn path=/head/; revision=339672
Diffstat (limited to 'sys/kern/vfs_init.c')
-rw-r--r--sys/kern/vfs_init.c220
1 files changed, 213 insertions, 7 deletions
diff --git a/sys/kern/vfs_init.c b/sys/kern/vfs_init.c
index 5eb38e6d8f61..58cde434b8f7 100644
--- a/sys/kern/vfs_init.c
+++ b/sys/kern/vfs_init.c
@@ -165,6 +165,198 @@ vfs_byname_kld(const char *fstype, struct thread *td, int *error)
return (vfsp);
}
+static int
+vfs_mount_sigdefer(struct mount *mp)
+{
+ int prev_stops, rc;
+
+ TSRAW(curthread, TS_ENTER, "VFS_MOUNT", mp->mnt_vfc->vfc_name);
+ prev_stops = sigdeferstop(SIGDEFERSTOP_SILENT);
+ rc = (*mp->mnt_vfc->vfc_vfsops_sd->vfs_mount)(mp);
+ sigallowstop(prev_stops);
+ TSRAW(curthread, TS_EXIT, "VFS_MOUNT", mp->mnt_vfc->vfc_name);
+ return (rc);
+}
+
+static int
+vfs_unmount_sigdefer(struct mount *mp, int mntflags)
+{
+ int prev_stops, rc;
+
+ prev_stops = sigdeferstop(SIGDEFERSTOP_SILENT);
+ rc = (*mp->mnt_vfc->vfc_vfsops_sd->vfs_unmount)(mp, mntflags);
+ sigallowstop(prev_stops);
+ return (rc);
+}
+
+static int
+vfs_root_sigdefer(struct mount *mp, int flags, struct vnode **vpp)
+{
+ int prev_stops, rc;
+
+ prev_stops = sigdeferstop(SIGDEFERSTOP_SILENT);
+ rc = (*mp->mnt_vfc->vfc_vfsops_sd->vfs_root)(mp, flags, vpp);
+ sigallowstop(prev_stops);
+ return (rc);
+}
+
+static int
+vfs_quotactl_sigdefer(struct mount *mp, int cmd, uid_t uid, void *arg)
+{
+ int prev_stops, rc;
+
+ prev_stops = sigdeferstop(SIGDEFERSTOP_SILENT);
+ rc = (*mp->mnt_vfc->vfc_vfsops_sd->vfs_quotactl)(mp, cmd, uid, arg);
+ sigallowstop(prev_stops);
+ return (rc);
+}
+
+static int
+vfs_statfs_sigdefer(struct mount *mp, struct statfs *sbp)
+{
+ int prev_stops, rc;
+
+ prev_stops = sigdeferstop(SIGDEFERSTOP_SILENT);
+ rc = (*mp->mnt_vfc->vfc_vfsops_sd->vfs_statfs)(mp, sbp);
+ sigallowstop(prev_stops);
+ return (rc);
+}
+
+static int
+vfs_sync_sigdefer(struct mount *mp, int waitfor)
+{
+ int prev_stops, rc;
+
+ prev_stops = sigdeferstop(SIGDEFERSTOP_SILENT);
+ rc = (*mp->mnt_vfc->vfc_vfsops_sd->vfs_sync)(mp, waitfor);
+ sigallowstop(prev_stops);
+ return (rc);
+}
+
+static int
+vfs_vget_sigdefer(struct mount *mp, ino_t ino, int flags, struct vnode **vpp)
+{
+ int prev_stops, rc;
+
+ prev_stops = sigdeferstop(SIGDEFERSTOP_SILENT);
+ rc = (*mp->mnt_vfc->vfc_vfsops_sd->vfs_vget)(mp, ino, flags, vpp);
+ sigallowstop(prev_stops);
+ return (rc);
+}
+
+static int
+vfs_fhtovp_sigdefer(struct mount *mp, struct fid *fidp, int flags,
+ struct vnode **vpp)
+{
+ int prev_stops, rc;
+
+ prev_stops = sigdeferstop(SIGDEFERSTOP_SILENT);
+ rc = (*mp->mnt_vfc->vfc_vfsops_sd->vfs_fhtovp)(mp, fidp, flags, vpp);
+ sigallowstop(prev_stops);
+ return (rc);
+}
+
+static int
+vfs_checkexp_sigdefer(struct mount *mp, struct sockaddr *nam, int *exflg,
+ struct ucred **credp, int *numsecflavors, int **secflavors)
+{
+ int prev_stops, rc;
+
+ prev_stops = sigdeferstop(SIGDEFERSTOP_SILENT);
+ rc = (*mp->mnt_vfc->vfc_vfsops_sd->vfs_checkexp)(mp, nam, exflg, credp,
+ numsecflavors, secflavors);
+ sigallowstop(prev_stops);
+ return (rc);
+}
+
+static int
+vfs_extattrctl_sigdefer(struct mount *mp, int cmd, struct vnode *filename_vp,
+ int attrnamespace, const char *attrname)
+{
+ int prev_stops, rc;
+
+ prev_stops = sigdeferstop(SIGDEFERSTOP_SILENT);
+ rc = (*mp->mnt_vfc->vfc_vfsops_sd->vfs_extattrctl)(mp, cmd,
+ filename_vp, attrnamespace, attrname);
+ sigallowstop(prev_stops);
+ return (rc);
+}
+
+static int
+vfs_sysctl_sigdefer(struct mount *mp, fsctlop_t op, struct sysctl_req *req)
+{
+ int prev_stops, rc;
+
+ prev_stops = sigdeferstop(SIGDEFERSTOP_SILENT);
+ rc = (*mp->mnt_vfc->vfc_vfsops_sd->vfs_sysctl)(mp, op, req);
+ sigallowstop(prev_stops);
+ return (rc);
+}
+
+static void
+vfs_susp_clean_sigdefer(struct mount *mp)
+{
+ int prev_stops;
+
+ if (*mp->mnt_vfc->vfc_vfsops_sd->vfs_susp_clean == NULL)
+ return;
+ prev_stops = sigdeferstop(SIGDEFERSTOP_SILENT);
+ (*mp->mnt_vfc->vfc_vfsops_sd->vfs_susp_clean)(mp);
+ sigallowstop(prev_stops);
+}
+
+static void
+vfs_reclaim_lowervp_sigdefer(struct mount *mp, struct vnode *vp)
+{
+ int prev_stops;
+
+ if (*mp->mnt_vfc->vfc_vfsops_sd->vfs_reclaim_lowervp == NULL)
+ return;
+ prev_stops = sigdeferstop(SIGDEFERSTOP_SILENT);
+ (*mp->mnt_vfc->vfc_vfsops_sd->vfs_reclaim_lowervp)(mp, vp);
+ sigallowstop(prev_stops);
+}
+
+static void
+vfs_unlink_lowervp_sigdefer(struct mount *mp, struct vnode *vp)
+{
+ int prev_stops;
+
+ if (*mp->mnt_vfc->vfc_vfsops_sd->vfs_unlink_lowervp == NULL)
+ return;
+ prev_stops = sigdeferstop(SIGDEFERSTOP_SILENT);
+ (*(mp)->mnt_vfc->vfc_vfsops_sd->vfs_unlink_lowervp)(mp, vp);
+ sigallowstop(prev_stops);
+}
+
+static void
+vfs_purge_sigdefer(struct mount *mp)
+{
+ int prev_stops;
+
+ prev_stops = sigdeferstop(SIGDEFERSTOP_SILENT);
+ (*mp->mnt_vfc->vfc_vfsops_sd->vfs_purge)(mp);
+ sigallowstop(prev_stops);
+}
+
+static struct vfsops vfsops_sigdefer = {
+ .vfs_mount = vfs_mount_sigdefer,
+ .vfs_unmount = vfs_unmount_sigdefer,
+ .vfs_root = vfs_root_sigdefer,
+ .vfs_quotactl = vfs_quotactl_sigdefer,
+ .vfs_statfs = vfs_statfs_sigdefer,
+ .vfs_sync = vfs_sync_sigdefer,
+ .vfs_vget = vfs_vget_sigdefer,
+ .vfs_fhtovp = vfs_fhtovp_sigdefer,
+ .vfs_checkexp = vfs_checkexp_sigdefer,
+ .vfs_extattrctl = vfs_extattrctl_sigdefer,
+ .vfs_sysctl = vfs_sysctl_sigdefer,
+ .vfs_susp_clean = vfs_susp_clean_sigdefer,
+ .vfs_reclaim_lowervp = vfs_reclaim_lowervp_sigdefer,
+ .vfs_unlink_lowervp = vfs_unlink_lowervp_sigdefer,
+ .vfs_purge = vfs_purge_sigdefer,
+
+};
/* Register a new filesystem type in the global table */
static int
@@ -278,13 +470,21 @@ vfs_register(struct vfsconf *vfc)
if (vfsops->vfs_sysctl == NULL)
vfsops->vfs_sysctl = vfs_stdsysctl;
+ if ((vfc->vfc_flags & VFCF_SBDRY) != 0) {
+ vfc->vfc_vfsops_sd = vfc->vfc_vfsops;
+ vfc->vfc_vfsops = &vfsops_sigdefer;
+ }
+
if (vfc->vfc_flags & VFCF_JAIL)
prison_add_vfs(vfc);
/*
* Call init function for this VFS...
*/
- (*(vfc->vfc_vfsops->vfs_init))(vfc);
+ if ((vfc->vfc_flags & VFCF_SBDRY) != 0)
+ vfc->vfc_vfsops_sd->vfs_init(vfc);
+ else
+ vfc->vfc_vfsops->vfs_init(vfc);
vfsconf_unlock();
/*
@@ -329,12 +529,18 @@ vfs_unregister(struct vfsconf *vfc)
vfsconf_unlock();
return (EBUSY);
}
- if (vfc->vfc_vfsops->vfs_uninit != NULL) {
- error = (*vfc->vfc_vfsops->vfs_uninit)(vfsp);
- if (error != 0) {
- vfsconf_unlock();
- return (error);
- }
+ error = 0;
+ if ((vfc->vfc_flags & VFCF_SBDRY) != 0) {
+ if (vfc->vfc_vfsops_sd->vfs_uninit != NULL)
+ error = vfc->vfc_vfsops_sd->vfs_uninit(vfsp);
+ } else {
+ if (vfc->vfc_vfsops->vfs_uninit != NULL) {
+ error = vfc->vfc_vfsops->vfs_uninit(vfsp);
+ }
+ if (error != 0) {
+ vfsconf_unlock();
+ return (error);
+ }
}
TAILQ_REMOVE(&vfsconf, vfsp, vfc_list);
maxtypenum = VFS_GENERIC;