svn commit: r190315 - in stable/7/sys: . contrib/pf dev/ath/ath_hal
dev/cxgb nfsclient
Craig Rodrigues
rodrigc at FreeBSD.org
Mon Mar 23 01:33:20 PDT 2009
Author: rodrigc
Date: Mon Mar 23 08:33:19 2009
New Revision: 190315
URL: http://svn.freebsd.org/changeset/base/190315
Log:
MFC 183005, 187812:
Add code to parse mount options passed as individual
items of the nmount() iovec.
Modified:
stable/7/sys/ (props changed)
stable/7/sys/contrib/pf/ (props changed)
stable/7/sys/dev/ath/ath_hal/ (props changed)
stable/7/sys/dev/cxgb/ (props changed)
stable/7/sys/nfsclient/nfs_vfsops.c
Modified: stable/7/sys/nfsclient/nfs_vfsops.c
==============================================================================
--- stable/7/sys/nfsclient/nfs_vfsops.c Mon Mar 23 05:46:28 2009 (r190314)
+++ stable/7/sys/nfsclient/nfs_vfsops.c Mon Mar 23 08:33:19 2009 (r190315)
@@ -717,7 +717,15 @@ nfs_decode_args(struct mount *mp, struct
}
}
-static const char *nfs_opts[] = { "from", "nfs_args", NULL };
+static const char *nfs_opts[] = { "from", "nfs_args",
+ "noatime", "noexec", "suiddir", "nosuid", "nosymfollow", "union",
+ "noclusterr", "noclusterw", "multilabel", "acls", "force", "update",
+ "async", "dumbtimer", "noconn", "nolockd", "intr", "rdirplus", "resvport",
+ "readdirsize", "soft", "hard", "mntudp", "tcp", "udp", "wsize", "rsize",
+ "retrans", "acregmin", "acregmax", "acdirmin", "acdirmax",
+ "deadthresh", "hostname", "timeout", "addr", "fh", "nfsv3",
+ "maxgroups",
+ NULL };
/*
* VFS Operations.
@@ -732,13 +740,20 @@ static const char *nfs_opts[] = { "from"
static int
nfs_mount(struct mount *mp, struct thread *td)
{
- int error;
+ int error, ret, has_nfs_args_opt;
+ int has_addr_opt, has_fh_opt, has_hostname_opt;
struct nfs_args args;
struct sockaddr *nam;
struct vnode *vp;
char hst[MNAMELEN];
size_t len;
u_char nfh[NFSX_V3FHMAX];
+ char *opt;
+
+ has_nfs_args_opt = 0;
+ has_addr_opt = 0;
+ has_fh_opt = 0;
+ has_hostname_opt = 0;
if (vfs_filteropt(mp->mnt_optnew, nfs_opts)) {
error = EINVAL;
@@ -750,12 +765,223 @@ nfs_mount(struct mount *mp, struct threa
goto out;
}
- error = vfs_copyopt(mp->mnt_optnew, "nfs_args", &args, sizeof args);
- if (error)
- goto out;
+ /*
+ * The old mount_nfs program passed the struct nfs_args
+ * from userspace to kernel. The new mount_nfs program
+ * passes string options via nmount() from userspace to kernel
+ * and we populate the struct nfs_args in the kernel.
+ */
+ if (vfs_getopt(mp->mnt_optnew, "nfs_args", NULL, NULL) == 0) {
+ error = vfs_copyopt(mp->mnt_optnew, "nfs_args", &args,
+ sizeof args);
+ if (error)
+ goto out;
+
+ if (args.version != NFS_ARGSVERSION) {
+ error = EPROGMISMATCH;
+ goto out;
+ }
+ has_nfs_args_opt = 1;
+ }
- if (args.version != NFS_ARGSVERSION) {
- error = EPROGMISMATCH;
+ if (vfs_getopt(mp->mnt_optnew, "dumbtimer", NULL, NULL) == 0)
+ args.flags |= NFSMNT_DUMBTIMR;
+ if (vfs_getopt(mp->mnt_optnew, "noconn", NULL, NULL) == 0)
+ args.flags |= NFSMNT_NOCONN;
+ if (vfs_getopt(mp->mnt_optnew, "conn", NULL, NULL) == 0)
+ args.flags |= NFSMNT_NOCONN;
+ if (vfs_getopt(mp->mnt_optnew, "nolockd", NULL, NULL) == 0)
+ args.flags |= NFSMNT_NOLOCKD;
+ if (vfs_getopt(mp->mnt_optnew, "lockd", NULL, NULL) == 0)
+ args.flags &= ~NFSMNT_NOLOCKD;
+ if (vfs_getopt(mp->mnt_optnew, "intr", NULL, NULL) == 0)
+ args.flags |= NFSMNT_INT;
+ if (vfs_getopt(mp->mnt_optnew, "rdirplus", NULL, NULL) == 0)
+ args.flags |= NFSMNT_RDIRPLUS;
+ if (vfs_getopt(mp->mnt_optnew, "resvport", NULL, NULL) == 0)
+ args.flags |= NFSMNT_RESVPORT;
+ if (vfs_getopt(mp->mnt_optnew, "noresvport", NULL, NULL) == 0)
+ args.flags &= ~NFSMNT_RESVPORT;
+ if (vfs_getopt(mp->mnt_optnew, "soft", NULL, NULL) == 0)
+ args.flags |= NFSMNT_SOFT;
+ if (vfs_getopt(mp->mnt_optnew, "hard", NULL, NULL) == 0)
+ args.flags &= ~NFSMNT_SOFT;
+ if (vfs_getopt(mp->mnt_optnew, "mntudp", NULL, NULL) == 0)
+ args.sotype = SOCK_DGRAM;
+ if (vfs_getopt(mp->mnt_optnew, "udp", NULL, NULL) == 0)
+ args.sotype = SOCK_DGRAM;
+ if (vfs_getopt(mp->mnt_optnew, "tcp", NULL, NULL) == 0)
+ args.sotype = SOCK_STREAM;
+ if (vfs_getopt(mp->mnt_optnew, "nfsv3", NULL, NULL) == 0)
+ args.flags |= NFSMNT_NFSV3;
+ if (vfs_getopt(mp->mnt_optnew, "readdirsize", (void **)&opt, NULL) == 0) {
+ if (opt == NULL) {
+ vfs_mount_error(mp, "illegal readdirsize");
+ error = EINVAL;
+ goto out;
+ }
+ ret = sscanf(opt, "%d", &args.readdirsize);
+ if (ret != 1 || args.readdirsize <= 0) {
+ vfs_mount_error(mp, "illegal readdirsize: %s",
+ opt);
+ error = EINVAL;
+ goto out;
+ }
+ args.flags |= NFSMNT_READDIRSIZE;
+ }
+ if (vfs_getopt(mp->mnt_optnew, "readahead", (void **)&opt, NULL) == 0) {
+ if (opt == NULL) {
+ vfs_mount_error(mp, "illegal readahead");
+ error = EINVAL;
+ goto out;
+ }
+ ret = sscanf(opt, "%d", &args.readahead);
+ if (ret != 1 || args.readahead <= 0) {
+ vfs_mount_error(mp, "illegal readahead: %s",
+ opt);
+ error = EINVAL;
+ goto out;
+ }
+ args.flags |= NFSMNT_READAHEAD;
+ }
+ if (vfs_getopt(mp->mnt_optnew, "wsize", (void **)&opt, NULL) == 0) {
+ if (opt == NULL) {
+ vfs_mount_error(mp, "illegal wsize");
+ error = EINVAL;
+ goto out;
+ }
+ ret = sscanf(opt, "%d", &args.wsize);
+ if (ret != 1 || args.wsize <= 0) {
+ vfs_mount_error(mp, "illegal wsize: %s",
+ opt);
+ error = EINVAL;
+ goto out;
+ }
+ args.flags |= NFSMNT_WSIZE;
+ }
+ if (vfs_getopt(mp->mnt_optnew, "rsize", (void **)&opt, NULL) == 0) {
+ if (opt == NULL) {
+ vfs_mount_error(mp, "illegal rsize");
+ error = EINVAL;
+ goto out;
+ }
+ ret = sscanf(opt, "%d", &args.rsize);
+ if (ret != 1 || args.rsize <= 0) {
+ vfs_mount_error(mp, "illegal wsize: %s",
+ opt);
+ error = EINVAL;
+ goto out;
+ }
+ args.flags |= NFSMNT_RSIZE;
+ }
+ if (vfs_getopt(mp->mnt_optnew, "retrans", (void **)&opt, NULL) == 0) {
+ if (opt == NULL) {
+ vfs_mount_error(mp, "illegal retrans");
+ error = EINVAL;
+ goto out;
+ }
+ ret = sscanf(opt, "%d", &args.retrans);
+ if (ret != 1 || args.retrans <= 0) {
+ vfs_mount_error(mp, "illegal retrans: %s",
+ opt);
+ error = EINVAL;
+ goto out;
+ }
+ args.flags |= NFSMNT_RETRANS;
+ }
+ if (vfs_getopt(mp->mnt_optnew, "acregmin", (void **)&opt, NULL) == 0) {
+ ret = sscanf(opt, "%d", &args.acregmin);
+ if (ret != 1 || args.acregmin < 0) {
+ vfs_mount_error(mp, "illegal acregmin: %s",
+ opt);
+ error = EINVAL;
+ goto out;
+ }
+ args.flags |= NFSMNT_ACREGMIN;
+ }
+ if (vfs_getopt(mp->mnt_optnew, "acregmax", (void **)&opt, NULL) == 0) {
+ ret = sscanf(opt, "%d", &args.acregmax);
+ if (ret != 1 || args.acregmax < 0) {
+ vfs_mount_error(mp, "illegal acregmax: %s",
+ opt);
+ error = EINVAL;
+ goto out;
+ }
+ args.flags |= NFSMNT_ACREGMAX;
+ }
+ if (vfs_getopt(mp->mnt_optnew, "acdirmin", (void **)&opt, NULL) == 0) {
+ ret = sscanf(opt, "%d", &args.acdirmin);
+ if (ret != 1 || args.acdirmin < 0) {
+ vfs_mount_error(mp, "illegal acdirmin: %s",
+ opt);
+ error = EINVAL;
+ goto out;
+ }
+ args.flags |= NFSMNT_ACDIRMIN;
+ }
+ if (vfs_getopt(mp->mnt_optnew, "acdirmax", (void **)&opt, NULL) == 0) {
+ ret = sscanf(opt, "%d", &args.acdirmax);
+ if (ret != 1 || args.acdirmax < 0) {
+ vfs_mount_error(mp, "illegal acdirmax: %s",
+ opt);
+ error = EINVAL;
+ goto out;
+ }
+ args.flags |= NFSMNT_ACDIRMAX;
+ }
+ if (vfs_getopt(mp->mnt_optnew, "deadthresh", (void **)&opt, NULL) == 0) {
+ ret = sscanf(opt, "%d", &args.deadthresh);
+ if (ret != 1 || args.deadthresh <= 0) {
+ vfs_mount_error(mp, "illegal deadthresh: %s",
+ opt);
+ error = EINVAL;
+ goto out;
+ }
+ args.flags |= NFSMNT_DEADTHRESH;
+ }
+ if (vfs_getopt(mp->mnt_optnew, "timeout", (void **)&opt, NULL) == 0) {
+ ret = sscanf(opt, "%d", &args.timeo);
+ if (ret != 1 || args.timeo <= 0) {
+ vfs_mount_error(mp, "illegal timeout: %s",
+ opt);
+ error = EINVAL;
+ goto out;
+ }
+ args.flags |= NFSMNT_TIMEO;
+ }
+ if (vfs_getopt(mp->mnt_optnew, "maxgroups", (void **)&opt, NULL) == 0) {
+ ret = sscanf(opt, "%d", &args.maxgrouplist);
+ if (ret != 1 || args.timeo <= 0) {
+ vfs_mount_error(mp, "illegal maxgroups: %s",
+ opt);
+ error = EINVAL;
+ goto out;
+ }
+ args.flags |= NFSMNT_MAXGRPS;
+ }
+ if (vfs_getopt(mp->mnt_optnew, "addr", (void **)&args.addr,
+ &args.addrlen) == 0) {
+ has_addr_opt = 1;
+ if (args.addrlen > SOCK_MAXADDRLEN) {
+ error = ENAMETOOLONG;
+ goto out;
+ }
+ MALLOC(nam, struct sockaddr *, args.addrlen, M_SONAME,
+ M_WAITOK);
+ bcopy(args.addr, nam, args.addrlen);
+ nam->sa_len = args.addrlen;
+ }
+ if (vfs_getopt(mp->mnt_optnew, "fh", (void **)&args.fh,
+ &args.fhsize) == 0) {
+ has_fh_opt = 1;
+ }
+ if (vfs_getopt(mp->mnt_optnew, "hostname", (void **)&args.hostname,
+ NULL) == 0) {
+ has_hostname_opt = 1;
+ }
+ if (args.hostname == NULL) {
+ vfs_mount_error(mp, "Invalid hostname");
+ error = EINVAL;
goto out;
}
if (mp->mnt_flag & MNT_UPDATE) {
@@ -788,23 +1014,38 @@ nfs_mount(struct mount *mp, struct threa
*/
if (nfs_ip_paranoia == 0)
args.flags |= NFSMNT_NOCONN;
- if (args.fhsize < 0 || args.fhsize > NFSX_V3FHMAX) {
- error = EINVAL;
- goto out;
+
+ if (has_nfs_args_opt) {
+ /*
+ * In the 'nfs_args' case, the pointers in the args
+ * structure are in userland - we copy them in here.
+ */
+ if (!has_fh_opt) {
+ error = copyin((caddr_t)args.fh, (caddr_t)nfh,
+ args.fhsize);
+ if (error) {
+ goto out;
+ }
+ args.fh = nfh;
+ }
+ if (!has_hostname_opt) {
+ error = copyinstr(args.hostname, hst, MNAMELEN-1, &len);
+ if (error) {
+ goto out;
+ }
+ bzero(&hst[len], MNAMELEN - len);
+ args.hostname = hst;
+ }
+ if (!has_addr_opt) {
+ /* sockargs() call must be after above copyin() calls */
+ error = getsockaddr(&nam, (caddr_t)args.addr,
+ args.addrlen);
+ if (error) {
+ goto out;
+ }
+ }
}
- error = copyin((caddr_t)args.fh, (caddr_t)nfh, args.fhsize);
- if (error)
- goto out;
- error = copyinstr(args.hostname, hst, MNAMELEN-1, &len);
- if (error)
- goto out;
- bzero(&hst[len], MNAMELEN - len);
- /* sockargs() call must be after above copyin() calls */
- error = getsockaddr(&nam, (caddr_t)args.addr, args.addrlen);
- if (error)
- goto out;
- args.fh = nfh;
- error = mountnfs(&args, mp, nam, hst, &vp, td->td_ucred);
+ error = mountnfs(&args, mp, nam, args.hostname, &vp, td->td_ucred);
out:
if (!error) {
MNT_ILOCK(mp);
More information about the svn-src-stable-7
mailing list