Convert the vfsconf list to a TAILQ.
Introduce vfs_byname() function to find things on it. Staticize vfs_nmount() function under the name vfs_donmount(). Various cleanups.
This commit is contained in:
parent
2cb640f6b1
commit
3dfe213e61
@ -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;
|
||||
|
@ -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) {
|
||||
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);
|
||||
}
|
||||
error = securelevel_gt(td->td_ucred, 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);
|
||||
}
|
||||
error = linker_load_module(NULL, fstype, NULL, NULL, &lf);
|
||||
if (error || lf == NULL) {
|
||||
if (va.va_uid != td->td_ucred->cr_uid) {
|
||||
if ((error = suser(td)) != 0) {
|
||||
vput(vp);
|
||||
return (error);
|
||||
}
|
||||
}
|
||||
if ((error = vinvalbuf(vp, V_SAVE, td->td_ucred, td, 0, 0)) != 0) {
|
||||
vput(vp);
|
||||
if (lf == NULL)
|
||||
error = ENODEV;
|
||||
return (error);
|
||||
}
|
||||
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;
|
||||
if (vfsp == NULL) {
|
||||
lf->userrefs--;
|
||||
linker_file_unload(lf, LINKER_UNLOAD_FORCE);
|
||||
if (vp->v_type != VDIR) {
|
||||
vput(vp);
|
||||
return (ENODEV);
|
||||
return (ENOTDIR);
|
||||
}
|
||||
}
|
||||
VI_LOCK(vp);
|
||||
if ((vp->v_iflag & VI_MOUNT) != 0 ||
|
||||
vp->v_mountedhere != NULL) {
|
||||
vfsp = vfs_byname(fstype);
|
||||
if (vfsp == NULL) {
|
||||
/* 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 (EBUSY);
|
||||
}
|
||||
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);
|
||||
|
@ -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;
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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 */
|
||||
|
Loading…
Reference in New Issue
Block a user