Page MenuHomeFreeBSD

D6347.id16289.diff
No OneTemporary

D6347.id16289.diff

Index: sys/fs/nfsclient/nfs_clvfsops.c
===================================================================
--- sys/fs/nfsclient/nfs_clvfsops.c
+++ sys/fs/nfsclient/nfs_clvfsops.c
@@ -741,6 +741,101 @@
NULL };
/*
+ * Parse the "from" mountarg, passed by the generic mount(8) program
+ * or the mountroot code. This is used when rerooting into NFS.
+ *
+ * Note that the "hostname" is actually a "hostname:/share/path" string.
+ */
+static int
+nfs_mount_parse_from(struct vfsoptlist *opts, char **hostnamep,
+ struct sockaddr_in **sinp, char *dirpath, size_t dirpathsize, int *dirlenp)
+{
+ char nam[MNAMELEN + 1];
+ char *delimp, *hostp, *spec;
+ int error, have_bracket = 0, offset, rv, speclen;
+ struct sockaddr_in *sin;
+ size_t len;
+
+ error = vfs_getopt(opts, "from", (void **)&spec, &speclen);
+ if (error != 0)
+ return (error);
+
+ /*
+ * This part comes from sbin/mount_nfs/mount_nfs.c:getnfsargs().
+ */
+ if (*spec == '[' && (delimp = strchr(spec + 1, ']')) != NULL &&
+ *(delimp + 1) == ':') {
+ hostp = spec + 1;
+ spec = delimp + 2;
+ have_bracket = 1;
+ } else if ((delimp = strrchr(spec, ':')) != NULL) {
+ hostp = spec;
+ spec = delimp + 1;
+ } else if ((delimp = strrchr(spec, '@')) != NULL) {
+ printf("%s: path@server syntax is deprecated, "
+ "use server:path\n", __func__);
+ hostp = delimp + 1;
+ } else {
+ printf("%s: no <host>:<dirpath> nfs-name\n", __func__);
+ return (EINVAL);
+ }
+ *delimp = '\0';
+
+ /*
+ * If there has been a trailing slash at mounttime it seems
+ * that some mountd implementations fail to remove the mount
+ * entries from their mountlist while unmounting.
+ */
+ for (speclen = strlen(spec);
+ speclen > 1 && spec[speclen - 1] == '/';
+ speclen--)
+ spec[speclen - 1] = '\0';
+ if (strlen(hostp) + strlen(spec) + 1 > MNAMELEN) {
+ printf("%s: %s:%s: name too long", __func__, hostp, spec);
+ return (EINVAL);
+ }
+ /* Make both '@' and ':' notations equal */
+ if (*hostp != '\0') {
+ len = strlen(hostp);
+ offset = 0;
+ if (have_bracket)
+ nam[offset++] = '[';
+ memmove(nam + offset, hostp, len);
+ if (have_bracket)
+ nam[len + offset++] = ']';
+ nam[len + offset++] = ':';
+ memmove(nam + len + offset, spec, speclen);
+ nam[len + speclen + offset] = '\0';
+ }
+
+ /*
+ * XXX: IPv6
+ */
+ sin = malloc(sizeof(*sin), M_SONAME, M_WAITOK);
+ rv = inet_pton(AF_INET, hostp, &sin->sin_addr);
+ if (rv != 1) {
+ printf("%s: cannot parse '%s', inet_pton() returned %d\n",
+ __func__, hostp, rv);
+ free(sin, M_SONAME);
+ return (EINVAL);
+ }
+
+ sin->sin_len = sizeof(*sin);
+ sin->sin_family = AF_INET;
+ /*
+ * XXX: hardcoded port number.
+ */
+ sin->sin_port = htons(2049);
+
+ *hostnamep = strdup(nam, M_NEWNFSMNT);
+ *sinp = sin;
+ strlcpy(dirpath, spec, dirpathsize);
+ *dirlenp = strlen(dirpath);
+
+ return (0);
+}
+
+/*
* VFS Operations.
*
* mount system call
@@ -785,17 +880,20 @@
int nametimeo = NFS_DEFAULT_NAMETIMEO;
int negnametimeo = NFS_DEFAULT_NEGNAMETIMEO;
int minvers = 0;
- int dirlen, has_nfs_args_opt, krbnamelen, srvkrbnamelen;
+ int dirlen, has_nfs_args_opt, has_nfs_from_opt,
+ krbnamelen, srvkrbnamelen;
size_t hstlen;
has_nfs_args_opt = 0;
+ has_nfs_from_opt = 0;
if (vfs_filteropt(mp->mnt_optnew, nfs_opts)) {
error = EINVAL;
goto out;
}
td = curthread;
- if ((mp->mnt_flag & (MNT_ROOTFS | MNT_UPDATE)) == MNT_ROOTFS) {
+ if ((mp->mnt_flag & (MNT_ROOTFS | MNT_UPDATE)) == MNT_ROOTFS &&
+ nfs_diskless_valid != 0) {
error = nfs_mountroot(mp);
goto out;
}
@@ -1135,6 +1233,19 @@
args.addrlen);
if (error != 0)
goto out;
+ } else if (nfs_mount_parse_from(mp->mnt_optnew,
+ &args.hostname, (struct sockaddr_in **)&nam, dirpath,
+ sizeof(dirpath), &dirlen) == 0) {
+ has_nfs_from_opt = 1;
+ bcopy(args.hostname, hst, MNAMELEN);
+ hst[MNAMELEN - 1] = '\0';
+
+ /*
+ * This only works with NFSv4 for now.
+ */
+ args.fhsize = 0;
+ args.flags |= NFSMNT_NFSV4;
+ args.sotype = SOCK_STREAM;
} else {
if (vfs_getopt(mp->mnt_optnew, "fh", (void **)&args.fh,
&args.fhsize) == 0) {
@@ -1174,13 +1285,16 @@
krbname[0] = '\0';
krbnamelen = strlen(krbname);
- if (vfs_getopt(mp->mnt_optnew, "dirpath", (void **)&name, NULL) == 0)
- strlcpy(dirpath, name, sizeof (dirpath));
- else
- dirpath[0] = '\0';
- dirlen = strlen(dirpath);
+ if (has_nfs_from_opt == 0) {
+ if (vfs_getopt(mp->mnt_optnew,
+ "dirpath", (void **)&name, NULL) == 0)
+ strlcpy(dirpath, name, sizeof (dirpath));
+ else
+ dirpath[0] = '\0';
+ dirlen = strlen(dirpath);
+ }
- if (has_nfs_args_opt == 0) {
+ if (has_nfs_args_opt == 0 && has_nfs_from_opt == 0) {
if (vfs_getopt(mp->mnt_optnew, "addr",
(void **)&args.addr, &args.addrlen) == 0) {
if (args.addrlen > SOCK_MAXADDRLEN) {

File Metadata

Mime Type
text/plain
Expires
Mon, Sep 28, 5:04 PM (4 h, 29 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
39820216
Default Alt Text
D6347.id16289.diff (4 KB)

Event Timeline