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:
Poul-Henning Kamp 2004-07-27 22:32:01 +00:00
parent 2cb640f6b1
commit 3dfe213e61
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=132710
5 changed files with 117 additions and 150 deletions

View File

@ -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;

View File

@ -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);

View File

@ -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;

View File

@ -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);
}

View File

@ -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 */