Page Menu
Home
FreeBSD
Search
Configure Global Search
Log In
Files
F173682340
D6347.id16289.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Flag For Later
Award Token
Size
4 KB
Referenced Files
None
Subscribers
None
D6347.id16289.diff
View Options
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
Details
Attached
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)
Attached To
Mode
D6347: Make it possible to reroot into NFS.
Attached
Detach File
Event Timeline
Log In to Comment