Date: Mon, 23 Mar 2009 08:33:19 +0000 (UTC) From: Craig Rodrigues <rodrigc@FreeBSD.org> To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-stable@freebsd.org, svn-src-stable-7@freebsd.org Subject: svn commit: r190315 - in stable/7/sys: . contrib/pf dev/ath/ath_hal dev/cxgb nfsclient Message-ID: <200903230833.n2N8XJd2000495@svn.freebsd.org>
next in thread | raw e-mail | index | archive | help
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);
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?200903230833.n2N8XJd2000495>