summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--sys/kern/vfs_init.c44
-rw-r--r--sys/kern/vfs_mount.c156
-rw-r--r--sys/kern/vfs_subr.c31
-rw-r--r--sys/libkern/iconv.c11
-rw-r--r--sys/sys/mount.h19
5 files changed, 114 insertions, 147 deletions
diff --git a/sys/kern/vfs_init.c b/sys/kern/vfs_init.c
index 9597519..999764a 100644
--- a/sys/kern/vfs_init.c
+++ b/sys/kern/vfs_init.c
@@ -57,7 +57,7 @@ int maxvfsconf = VFS_GENERIC + 1;
* Single-linked list of configured VFSes.
* New entries are added/deleted by vfs_register()/vfs_unregister()
*/
-struct vfsconf *vfsconf;
+struct vfsconfhead vfsconf = TAILQ_HEAD_INITIALIZER(vfsconf);
/*
* vfs_init.c
@@ -349,6 +349,17 @@ vfs_rm_vnodeops(const void *data)
*/
struct vattr va_null;
+struct vfsconf *
+vfs_byname(const char *name)
+{
+ struct vfsconf *vfsp;
+
+ TAILQ_FOREACH(vfsp, &vfsconf, vfc_list)
+ if (!strcmp(name, vfsp->vfc_name))
+ return (vfsp);
+ return (NULL);
+}
+
/*
* Initialize the vnode structures and initialize each filesystem type.
*/
@@ -366,22 +377,13 @@ int
vfs_register(struct vfsconf *vfc)
{
struct sysctl_oid *oidp;
- struct vfsconf *vfsp;
-
struct vfsops *vfsops;
- vfsp = NULL;
- if (vfsconf)
- for (vfsp = vfsconf; vfsp->vfc_next; vfsp = vfsp->vfc_next)
- if (strcmp(vfc->vfc_name, vfsp->vfc_name) == 0)
- return EEXIST;
+ if (vfs_byname(vfc->vfc_name) != NULL)
+ return EEXIST;
vfc->vfc_typenum = maxvfsconf++;
- if (vfsp)
- vfsp->vfc_next = vfc;
- else
- vfsconf = vfc;
- vfc->vfc_next = NULL;
+ TAILQ_INSERT_TAIL(&vfsconf, vfc, vfc_list);
/*
* If this filesystem has a sysctl node under vfs
@@ -474,17 +476,12 @@ vfs_register(struct vfsconf *vfc)
int
vfs_unregister(struct vfsconf *vfc)
{
- struct vfsconf *vfsp, *prev_vfsp;
+ struct vfsconf *vfsp;
int error, i, maxtypenum;
i = vfc->vfc_typenum;
- prev_vfsp = NULL;
- for (vfsp = vfsconf; vfsp;
- prev_vfsp = vfsp, vfsp = vfsp->vfc_next) {
- if (!strcmp(vfc->vfc_name, vfsp->vfc_name))
- break;
- }
+ vfsp = vfs_byname(vfc->vfc_name);
if (vfsp == NULL)
return EINVAL;
if (vfsp->vfc_refcount)
@@ -494,12 +491,9 @@ vfs_unregister(struct vfsconf *vfc)
if (error)
return (error);
}
- if (prev_vfsp)
- prev_vfsp->vfc_next = vfsp->vfc_next;
- else
- vfsconf = vfsp->vfc_next;
+ TAILQ_REMOVE(&vfsconf, vfsp, vfc_list);
maxtypenum = VFS_GENERIC;
- for (vfsp = vfsconf; vfsp != NULL; vfsp = vfsp->vfc_next)
+ TAILQ_FOREACH(vfsp, &vfsconf, vfc_list)
if (maxtypenum < vfsp->vfc_typenum)
maxtypenum = vfsp->vfc_typenum;
maxvfsconf = maxtypenum + 1;
diff --git a/sys/kern/vfs_mount.c b/sys/kern/vfs_mount.c
index cf7b7c1..5694fa5 100644
--- a/sys/kern/vfs_mount.c
+++ b/sys/kern/vfs_mount.c
@@ -105,6 +105,8 @@ static int vfs_mount_alloc(struct vnode *dvp, struct vfsconf *vfsp,
const char *fspath, struct thread *td, struct mount **mpp);
static int vfs_mountroot_ask(void);
static int vfs_mountroot_try(char *mountfrom);
+static int vfs_donmount(struct thread *td, int fsflags,
+ struct uio *fsoptions);
static int usermount = 0;
SYSCTL_INT(_vfs, OID_AUTO, usermount, CTLFLAG_RW, &usermount, 0,
@@ -400,16 +402,13 @@ nmount(td, uap)
}
iov++;
}
- error = vfs_nmount(td, uap->flags, auio);
+ error = vfs_donmount(td, uap->flags, auio);
free(auio, M_IOV);
return (error);
}
int
-kernel_mount(iovp, iovcnt, flags)
- struct iovec *iovp;
- unsigned int iovcnt;
- int flags;
+kernel_mount(struct iovec *iovp, u_int iovcnt, int flags)
{
struct uio auio;
int error;
@@ -425,7 +424,7 @@ kernel_mount(iovp, iovcnt, flags)
auio.uio_iovcnt = iovcnt;
auio.uio_segflg = UIO_SYSSPACE;
- error = vfs_nmount(curthread, flags, &auio);
+ error = vfs_donmount(curthread, flags, &auio);
return (error);
}
@@ -435,7 +434,7 @@ kernel_vmount(int flags, ...)
struct iovec *iovp;
struct uio auio;
va_list ap;
- unsigned int iovcnt, iovlen, len;
+ u_int iovcnt, iovlen, len;
const char *cp;
char *buf, *pos;
size_t n;
@@ -468,7 +467,7 @@ kernel_vmount(int flags, ...)
auio.uio_iovcnt = iovcnt;
auio.uio_segflg = UIO_SYSSPACE;
- error = vfs_nmount(curthread, flags, &auio);
+ error = vfs_donmount(curthread, flags, &auio);
FREE(iovp, M_MOUNT);
FREE(buf, M_MOUNT);
return (error);
@@ -532,8 +531,8 @@ vfs_mount_destroy(struct mount *mp, struct thread *td)
free(mp, M_MOUNT);
}
-int
-vfs_nmount(struct thread *td, int fsflags, struct uio *fsoptions)
+static int
+vfs_donmount(struct thread *td, int fsflags, struct uio *fsoptions)
{
struct vfsoptlist *optlist;
char *fstype, *fspath;
@@ -746,88 +745,83 @@ vfs_domount(
mp->mnt_optnew = fsdata;
vfs_mergeopts(mp->mnt_optnew, mp->mnt_opt);
}
- goto update;
- }
- /*
- * If the user is not root, ensure that they own the directory
- * onto which we are attempting to mount.
- */
- error = VOP_GETATTR(vp, &va, td->td_ucred, td);
- if (error) {
- vput(vp);
- return (error);
- }
- if (va.va_uid != td->td_ucred->cr_uid) {
- if ((error = suser(td)) != 0) {
+ } else {
+ /*
+ * If the user is not root, ensure that they own the directory
+ * onto which we are attempting to mount.
+ */
+ error = VOP_GETATTR(vp, &va, td->td_ucred, td);
+ if (error) {
vput(vp);
return (error);
}
- }
- if ((error = vinvalbuf(vp, V_SAVE, td->td_ucred, td, 0, 0)) != 0) {
- vput(vp);
- return (error);
- }
- if (vp->v_type != VDIR) {
- vput(vp);
- return (ENOTDIR);
- }
- for (vfsp = vfsconf; vfsp; vfsp = vfsp->vfc_next)
- if (strcmp(vfsp->vfc_name, fstype) == 0)
- break;
- if (vfsp == NULL) {
- /* Only load modules for root (very important!). */
- if ((error = suser(td)) != 0) {
- vput(vp);
- return (error);
+ if (va.va_uid != td->td_ucred->cr_uid) {
+ if ((error = suser(td)) != 0) {
+ vput(vp);
+ return (error);
+ }
}
- error = securelevel_gt(td->td_ucred, 0);
- if (error) {
+ if ((error = vinvalbuf(vp, V_SAVE, td->td_ucred, td, 0, 0)) != 0) {
vput(vp);
return (error);
}
- error = linker_load_module(NULL, fstype, NULL, NULL, &lf);
- if (error || lf == NULL) {
+ if (vp->v_type != VDIR) {
vput(vp);
- if (lf == NULL)
- error = ENODEV;
- return (error);
+ return (ENOTDIR);
}
- lf->userrefs++;
- /* Look up again to see if the VFS was loaded. */
- for (vfsp = vfsconf; vfsp; vfsp = vfsp->vfc_next)
- if (strcmp(vfsp->vfc_name, fstype) == 0)
- break;
+ vfsp = vfs_byname(fstype);
if (vfsp == NULL) {
- lf->userrefs--;
- linker_file_unload(lf, LINKER_UNLOAD_FORCE);
+ /* Only load modules for root (very important!). */
+ if ((error = suser(td)) != 0) {
+ vput(vp);
+ return (error);
+ }
+ error = securelevel_gt(td->td_ucred, 0);
+ if (error) {
+ vput(vp);
+ return (error);
+ }
+ error = linker_load_module(NULL, fstype, NULL, NULL, &lf);
+ if (error || lf == NULL) {
+ vput(vp);
+ if (lf == NULL)
+ error = ENODEV;
+ return (error);
+ }
+ lf->userrefs++;
+ /* Look up again to see if the VFS was loaded. */
+ vfsp = vfs_byname(fstype);
+ if (vfsp == NULL) {
+ lf->userrefs--;
+ linker_file_unload(lf, LINKER_UNLOAD_FORCE);
+ vput(vp);
+ return (ENODEV);
+ }
+ }
+ VI_LOCK(vp);
+ if ((vp->v_iflag & VI_MOUNT) != 0 ||
+ vp->v_mountedhere != NULL) {
+ VI_UNLOCK(vp);
vput(vp);
- return (ENODEV);
+ return (EBUSY);
}
- }
- VI_LOCK(vp);
- if ((vp->v_iflag & VI_MOUNT) != 0 ||
- vp->v_mountedhere != NULL) {
+ vp->v_iflag |= VI_MOUNT;
VI_UNLOCK(vp);
- vput(vp);
- return (EBUSY);
- }
- vp->v_iflag |= VI_MOUNT;
- VI_UNLOCK(vp);
- /*
- * Allocate and initialize the filesystem.
- */
- error = vfs_mount_alloc(vp, vfsp, fspath, td, &mp);
- if (error) {
- vput(vp);
- return (error);
- }
- VOP_UNLOCK(vp, 0, td);
+ /*
+ * Allocate and initialize the filesystem.
+ */
+ error = vfs_mount_alloc(vp, vfsp, fspath, td, &mp);
+ if (error) {
+ vput(vp);
+ return (error);
+ }
+ VOP_UNLOCK(vp, 0, td);
- /* XXXMAC: pass to vfs_mount_alloc? */
- if (compat == 0)
- mp->mnt_optnew = fsdata;
-update:
+ /* XXXMAC: pass to vfs_mount_alloc? */
+ if (compat == 0)
+ mp->mnt_optnew = fsdata;
+ }
/*
* Check if the fs implements the type VFS_[N]MOUNT()
* function we are looking for.
@@ -1182,9 +1176,7 @@ vfs_rootmountalloc(fstypename, devname, mpp)
if (fstypename == NULL)
return (ENODEV);
- for (vfsp = vfsconf; vfsp; vfsp = vfsp->vfc_next)
- if (!strcmp(vfsp->vfc_name, fstypename))
- break;
+ vfsp = vfs_byname(fstypename);
if (vfsp == NULL)
return (ENODEV);
error = vfs_mount_alloc(NULLVP, vfsp, "/", td, &mp);
@@ -1450,10 +1442,8 @@ getdiskbyname(char *name)
if (!bcmp(cp, "/dev/", 5))
cp += 5;
- for (vfsp = vfsconf; vfsp; vfsp = vfsp->vfc_next)
- if (!strcmp(vfsp->vfc_name, "devfs"))
- break;
do {
+ vfsp = vfs_byname("devfs");
if (vfsp == NULL)
break;
error = vfs_mount_alloc(NULLVP, vfsp, "/dev", td, &mp);
diff --git a/sys/kern/vfs_subr.c b/sys/kern/vfs_subr.c
index 846ae76..c89c9ea 100644
--- a/sys/kern/vfs_subr.c
+++ b/sys/kern/vfs_subr.c
@@ -2882,27 +2882,16 @@ static int
sysctl_vfs_conflist(SYSCTL_HANDLER_ARGS)
{
struct vfsconf *vfsp;
- struct xvfsconf *xvfsp;
- int cnt, error, i;
+ struct xvfsconf xvfsp;
+ int error;
- cnt = 0;
- for (vfsp = vfsconf; vfsp != NULL; vfsp = vfsp->vfc_next)
- cnt++;
- xvfsp = malloc(sizeof(struct xvfsconf) * cnt, M_TEMP, M_WAITOK);
- /*
- * Handle the race that we will have here when struct vfsconf
- * will be locked down by using both cnt and checking vfc_next
- * against NULL to determine the end of the loop. The race will
- * happen because we will have to unlock before calling malloc().
- * We are protected by Giant for now.
- */
- i = 0;
- for (vfsp = vfsconf; vfsp != NULL && i < cnt; vfsp = vfsp->vfc_next) {
- vfsconf2x(vfsp, xvfsp + i);
- i++;
+ error = 0;
+ TAILQ_FOREACH(vfsp, &vfsconf, vfc_list) {
+ vfsconf2x(vfsp, &xvfsp);
+ error = SYSCTL_OUT(req, &xvfsp, sizeof xvfsp);
+ if (error)
+ break;
}
- error = SYSCTL_OUT(req, xvfsp, sizeof(struct xvfsconf) * i);
- free(xvfsp, M_TEMP);
return (error);
}
@@ -2937,7 +2926,7 @@ vfs_sysctl(SYSCTL_HANDLER_ARGS)
case VFS_CONF:
if (namelen != 3)
return (ENOTDIR); /* overloaded */
- for (vfsp = vfsconf; vfsp; vfsp = vfsp->vfc_next)
+ TAILQ_FOREACH(vfsp, &vfsconf, vfc_list)
if (vfsp->vfc_typenum == name[2])
break;
if (vfsp == NULL)
@@ -2960,7 +2949,7 @@ sysctl_ovfs_conf(SYSCTL_HANDLER_ARGS)
struct vfsconf *vfsp;
struct ovfsconf ovfs;
- for (vfsp = vfsconf; vfsp; vfsp = vfsp->vfc_next) {
+ TAILQ_FOREACH(vfsp, &vfsconf, vfc_list) {
ovfs.vfc_vfsops = vfsp->vfc_vfsops; /* XXX used as flag */
strcpy(ovfs.vfc_name, vfsp->vfc_name);
ovfs.vfc_index = vfsp->vfc_typenum;
diff --git a/sys/libkern/iconv.c b/sys/libkern/iconv.c
index 462a2cf..cfdc28a 100644
--- a/sys/libkern/iconv.c
+++ b/sys/libkern/iconv.c
@@ -518,13 +518,8 @@ iconv_vfs_refcount(const char *fsname)
{
struct vfsconf *vfsp;
- for (vfsp = vfsconf; vfsp; vfsp = vfsp->vfc_next) {
- if (!strcmp(vfsp->vfc_name, fsname)) {
- if (vfsp->vfc_refcount > 0)
- return (EBUSY);
- else
- return (0);
- }
- }
+ vfsp = vfs_byname(fsname);
+ if (vfsp != NULL && vfsp->vfc_refcount > 0)
+ return (EBUSY);
return (0);
}
diff --git a/sys/sys/mount.h b/sys/sys/mount.h
index a9b7081..fc66ae3 100644
--- a/sys/sys/mount.h
+++ b/sys/sys/mount.h
@@ -346,7 +346,7 @@ struct vfsconf {
int vfc_refcount; /* number mounted of this type */
int vfc_flags; /* permanent flags */
struct vfsoptdecl *vfc_opts; /* mount options */
- struct vfsconf *vfc_next; /* next in list */
+ TAILQ_ENTRY(vfsconf) vfc_list; /* list of vfscons */
};
/* Userland version of the struct vfsconf. */
@@ -451,7 +451,9 @@ MALLOC_DECLARE(M_MOUNT);
#endif
extern int maxvfsconf; /* highest defined filesystem type */
extern int nfs_mount_type; /* vfc_typenum for nfs, or -1 */
-extern struct vfsconf *vfsconf; /* head of list of filesystem types */
+
+TAILQ_HEAD(vfsconfhead, vfsconf);
+extern struct vfsconfhead vfsconf;
/*
* Operations supported on mounted filesystem.
@@ -532,13 +534,10 @@ struct vfsops {
#define VFS_SET(vfsops, fsname, flags) \
static struct vfsconf fsname ## _vfsconf = { \
- &vfsops, \
- #fsname, \
- -1, \
- 0, \
- flags, \
- NULL, \
- NULL \
+ .vfc_vfsops = &vfsops, \
+ .vfc_name = #fsname, \
+ .vfc_typenum = -1, \
+ .vfc_flags = flags, \
}; \
static moduledata_t fsname ## _mod = { \
#fsname, \
@@ -555,11 +554,11 @@ extern char *mountrootfsname;
int dounmount(struct mount *, int, struct thread *);
int kernel_mount(struct iovec *, u_int, int);
int kernel_vmount(int flags, ...);
+struct vfsconf *vfs_byname(const char *);
void vfs_event_signal(fsid_t *, u_int32_t, intptr_t);
int vfs_getopt(struct vfsoptlist *, const char *, void **, int *);
int vfs_copyopt(struct vfsoptlist *, const char *, void *, int);
int vfs_mount(struct thread *, const char *, char *, int, void *);
-int vfs_nmount(struct thread *, int, struct uio *);
int vfs_setpublicfs /* set publicly exported fs */
(struct mount *, struct netexport *, struct export_args *);
int vfs_lock(struct mount *); /* lock a vfs */
OpenPOWER on IntegriCloud