Change the way we internally store the mount options to

a linked list.  This is to allow the merging of the mount
options in the MNT_UPDATE case, as the current data structure
is unsuitable for this.

There are no functional differences in this commit.

Reviewed by:	phk
This commit is contained in:
Maxime Henrion 2002-06-20 20:03:42 +00:00
parent 9f3d7bf758
commit 7d2d440991
4 changed files with 83 additions and 134 deletions

View File

@ -87,7 +87,6 @@ static int setutimes(struct thread *td, struct vnode *,
const struct timespec *, int);
static int vn_access(struct vnode *vp, int user_flags, struct ucred *cred,
struct thread *td);
static void vfs_freeopts(struct vfsoptlist *opt);
static int vfs_nmount(struct thread *td, int, struct uio *);
static int usermount = 0; /* if 1, non-root can mount fs. */
@ -167,13 +166,19 @@ nmount(td, uap)
* Release all resources related to the
* mount options.
*/
static void
vfs_freeopts(struct vfsoptlist *opt)
void
vfs_freeopts(struct vfsoptlist *opts)
{
struct vfsopt *opt;
free(opt->opt, M_MOUNT);
free(opt->optbuf, M_MOUNT);
free(opt, M_MOUNT);
while (!TAILQ_EMPTY(opts)) {
opt = TAILQ_FIRST(opts);
TAILQ_REMOVE(opts, opt, link);
free(opt->name, M_MOUNT);
free(opt->value, M_MOUNT);
free(opt, M_MOUNT);
}
free(opts, M_MOUNT);
}
int
@ -275,63 +280,16 @@ vfs_nmount(td, fsflags, fsoptions)
struct vnode *vp;
struct mount *mp;
struct vfsconf *vfsp;
struct iovec *cur;
struct vfsoptlist *optlist;
struct vfsopt *opt;
char *buf, *fstype, *fspath;
int error, flag = 0, kern_flag = 0, i, len, optcnt;
int offset, iovcnt, fstypelen, fspathlen;
char *fstype, *fspath;
int error, flag = 0, kern_flag = 0;
int fstypelen, fspathlen;
struct vattr va;
struct nameidata nd;
/*
* Allocate memory to hold the vfsopt structures.
*/
iovcnt = fsoptions->uio_iovcnt;
optcnt = iovcnt >> 1;
opt = malloc(sizeof (struct vfsopt) * optcnt,
M_MOUNT, M_WAITOK | M_ZERO);
/*
* Count the size of the buffer for options,
* allocate it, and fill in the vfsopt structures.
*/
cur = fsoptions->uio_iov;
len = fsoptions->uio_resid;
buf = malloc(len, M_TEMP, M_WAITOK | M_ZERO);
optlist = malloc(sizeof (struct vfsoptlist), M_MOUNT, M_WAITOK);
optlist->opt = opt;
optlist->optbuf = buf;
optlist->optcnt = optcnt;
offset = i = 0;
cur = fsoptions->uio_iov;
while (i < optcnt) {
opt[i].name = buf + offset;
/* Ensure the name of an option is a string. */
if (opt[i].name[cur->iov_len - 1] != '\0') {
error = EINVAL;
goto bad;
}
offset += cur->iov_len;
cur++;
opt[i].len = cur->iov_len;
/*
* Prevent consumers from trying to
* read the value of a 0 length option
* by setting it to NULL.
*/
if (opt[i].len == 0)
opt[i].value = NULL;
else
opt[i].value = buf + offset;
offset += cur->iov_len;
cur++; i++;
}
if ((error = uiomove(buf, len, fsoptions)) != 0)
goto bad;
error = vfs_buildopts(fsoptions, &optlist);
if (error)
return (error);
/*
* We need these two options before the others,

View File

@ -488,6 +488,49 @@ vfs_timestamp(tsp)
}
}
/*
* Build a linked list of mount options from a struct uio.
*/
int
vfs_buildopts(struct uio *auio, struct vfsoptlist **options)
{
struct vfsoptlist *opts;
struct vfsopt *opt;
unsigned int i, iovcnt;
int error, namelen, optlen;
iovcnt = auio->uio_iovcnt;
opts = malloc(sizeof(struct vfsoptlist), M_MOUNT, M_WAITOK);
TAILQ_INIT(opts);
for (i = 0; i < iovcnt; i += 2) {
opt = malloc(sizeof(struct vfsopt), M_MOUNT, M_WAITOK);
namelen = auio->uio_iov[i].iov_len;
optlen = auio->uio_iov[i + 1].iov_len;
opt->name = malloc(namelen, M_MOUNT, M_WAITOK);
opt->value = malloc(optlen, M_MOUNT, M_WAITOK);
opt->len = optlen;
if (auio->uio_segflg == UIO_SYSSPACE) {
bcopy(auio->uio_iov[i].iov_base, opt->name, namelen);
bcopy(auio->uio_iov[i + 1].iov_base, opt->value,
optlen);
} else {
error = copyin(auio->uio_iov[i].iov_base, opt->name,
namelen);
if (!error)
error = copyin(auio->uio_iov[i + 1].iov_base,
opt->value, optlen);
if (error)
goto bad;
}
TAILQ_INSERT_TAIL(opts, opt, link);
}
*options = opts;
return (0);
bad:
vfs_freeopts(opts);
return (error);
}
/*
* Get a mount option by its name.
*
@ -504,11 +547,8 @@ vfs_getopt(opts, name, buf, len)
int *len;
{
struct vfsopt *opt;
int i;
i = 0;
opt = opts->opt;
while (i++ < opts->optcnt) {
TAILQ_FOREACH(opt, opts, link) {
if (strcmp(name, opt->name) == 0) {
if (len != NULL)
*len = opt->len;
@ -516,7 +556,6 @@ vfs_getopt(opts, name, buf, len)
*buf = opt->value;
return (0);
}
opt++;
}
return (ENOENT);
}
@ -537,18 +576,14 @@ vfs_copyopt(opts, name, dest, len)
int len;
{
struct vfsopt *opt;
int i;
i = 0;
opt = opts->opt;
while (i++ < opts->optcnt) {
TAILQ_FOREACH(opt, opts, link) {
if (strcmp(name, opt->name) == 0) {
if (len != opt->len)
return (EINVAL);
bcopy(opt->value, dest, opt->len);
return (0);
}
opt++;
}
return (ENOENT);
}

View File

@ -87,7 +87,6 @@ static int setutimes(struct thread *td, struct vnode *,
const struct timespec *, int);
static int vn_access(struct vnode *vp, int user_flags, struct ucred *cred,
struct thread *td);
static void vfs_freeopts(struct vfsoptlist *opt);
static int vfs_nmount(struct thread *td, int, struct uio *);
static int usermount = 0; /* if 1, non-root can mount fs. */
@ -167,13 +166,19 @@ nmount(td, uap)
* Release all resources related to the
* mount options.
*/
static void
vfs_freeopts(struct vfsoptlist *opt)
void
vfs_freeopts(struct vfsoptlist *opts)
{
struct vfsopt *opt;
free(opt->opt, M_MOUNT);
free(opt->optbuf, M_MOUNT);
free(opt, M_MOUNT);
while (!TAILQ_EMPTY(opts)) {
opt = TAILQ_FIRST(opts);
TAILQ_REMOVE(opts, opt, link);
free(opt->name, M_MOUNT);
free(opt->value, M_MOUNT);
free(opt, M_MOUNT);
}
free(opts, M_MOUNT);
}
int
@ -275,63 +280,16 @@ vfs_nmount(td, fsflags, fsoptions)
struct vnode *vp;
struct mount *mp;
struct vfsconf *vfsp;
struct iovec *cur;
struct vfsoptlist *optlist;
struct vfsopt *opt;
char *buf, *fstype, *fspath;
int error, flag = 0, kern_flag = 0, i, len, optcnt;
int offset, iovcnt, fstypelen, fspathlen;
char *fstype, *fspath;
int error, flag = 0, kern_flag = 0;
int fstypelen, fspathlen;
struct vattr va;
struct nameidata nd;
/*
* Allocate memory to hold the vfsopt structures.
*/
iovcnt = fsoptions->uio_iovcnt;
optcnt = iovcnt >> 1;
opt = malloc(sizeof (struct vfsopt) * optcnt,
M_MOUNT, M_WAITOK | M_ZERO);
/*
* Count the size of the buffer for options,
* allocate it, and fill in the vfsopt structures.
*/
cur = fsoptions->uio_iov;
len = fsoptions->uio_resid;
buf = malloc(len, M_TEMP, M_WAITOK | M_ZERO);
optlist = malloc(sizeof (struct vfsoptlist), M_MOUNT, M_WAITOK);
optlist->opt = opt;
optlist->optbuf = buf;
optlist->optcnt = optcnt;
offset = i = 0;
cur = fsoptions->uio_iov;
while (i < optcnt) {
opt[i].name = buf + offset;
/* Ensure the name of an option is a string. */
if (opt[i].name[cur->iov_len - 1] != '\0') {
error = EINVAL;
goto bad;
}
offset += cur->iov_len;
cur++;
opt[i].len = cur->iov_len;
/*
* Prevent consumers from trying to
* read the value of a 0 length option
* by setting it to NULL.
*/
if (opt[i].len == 0)
opt[i].value = NULL;
else
opt[i].value = buf + offset;
offset += cur->iov_len;
cur++; i++;
}
if ((error = uiomove(buf, len, fsoptions)) != 0)
goto bad;
error = vfs_buildopts(fsoptions, &optlist);
if (error)
return (error);
/*
* We need these two options before the others,

View File

@ -120,13 +120,9 @@ struct statfs {
*/
TAILQ_HEAD(vnodelst, vnode);
struct vfsoptlist {
struct vfsopt *opt;
unsigned int optcnt;
char *optbuf;
};
TAILQ_HEAD(vfsoptlist, vfsopt);
struct vfsopt {
TAILQ_ENTRY(vfsopt) link;
char *name;
void *value;
int len;
@ -439,6 +435,8 @@ extern char *mountrootfsname;
int dounmount(struct mount *, int, struct thread *td);
int kernel_mount(struct iovec *iovp, unsigned int iovcnt, int flags);
int kernel_vmount(int flags, ...);
int vfs_buildopts(struct uio *, struct vfsoptlist **);
void vfs_freeopts(struct vfsoptlist *);
int vfs_getopt(struct vfsoptlist *, const char *, void **, int *);
int vfs_copyopt(struct vfsoptlist *, const char *, void *, int);
int vfs_mount(struct thread *td, const char *type, char *path,