> On May 6, 2021, at 9:48 PM, NeilBrown <neilb@xxxxxxx> wrote: > > > [[This is a proposed fix. It seems to work. I'd like > some review comments before it is committed. > Petr: it would be great if you could test it to confirm > it actually works in your case. > ]] > > Some filesystems cannot be exported without an fsid or uuid. > tmpfs is the main example. > > When mountd creates nfsv4 pseudo-root exports for the path leading down > to an export point it exports each directory without any fsid or uuid. > If one of these directories is on tmp, that will fail. > > The net result is that exporting a subdirectory of a tmpfs filesystem > will not work over NFSv4 as the parents within the filesystem cannot be > exported. It will either fail, or fall-back to NFSv3 (depending on the > version of the mount.nfs program). > > To fix this we need to provide an fsid or uuid for these pseudo-root > exports. This patch does that by creating a UUID with the first 4 bytes > 0xFFFFFFFF and the remaining 12 bytes form from the path name, xoring > bytes together if the path is longer than 12 characters. > Hopefully no filesystem uses a UUID like this.... That's not really a UUID, as per RFC 4122. I'm guessing it's possible for a collision to occur pretty quickly, for instance. It would be nicer if a conformant UUID could be used here. Is there a problem with specifying the export's fsid in /etc/exports? > The patch borrows some code from exportfs. Maybe that code should be > move to a library.. > > Signed-off-by: NeilBrown <neilb@xxxxxxx> > --- > support/export/v4root.c | 57 +++++++++++++++++++++++++++++++++++++++++ > 1 file changed, 57 insertions(+) > > diff --git a/support/export/v4root.c b/support/export/v4root.c > index 3654bd7c10c0..fd36eb704441 100644 > --- a/support/export/v4root.c > +++ b/support/export/v4root.c > @@ -11,6 +11,7 @@ > #include <config.h> > #endif > > +#include <fcntl.h> > #include <sys/types.h> > #include <sys/stat.h> > #include <sys/queue.h> > @@ -21,6 +22,7 @@ > #include <unistd.h> > #include <errno.h> > > +#include "nfsd_path.h" > #include "xlog.h" > #include "exportfs.h" > #include "nfslib.h" > @@ -73,6 +75,38 @@ set_pseudofs_security(struct exportent *pseudo) > } > } > > +static ssize_t exportfs_write(int fd, const char *buf, size_t len) > +{ > + return nfsd_path_write(fd, buf, len); > +} > + > +static int test_export(struct exportent *eep, int with_fsid) > +{ > + char *path = eep->e_path; > + int flags = eep->e_flags | (with_fsid ? NFSEXP_FSID : 0); > + /* beside max path, buf size should take protocol str into account */ > + char buf[NFS_MAXPATHLEN+1+64] = { 0 }; > + char *bp = buf; > + int len = sizeof(buf); > + int fd, n; > + > + n = snprintf(buf, len, "-test-client- "); > + bp += n; > + len -= n; > + qword_add(&bp, &len, path); > + if (len < 1) > + return 0; > + snprintf(bp, len, " 3 %d 65534 65534 0\n", flags); > + fd = open("/proc/net/rpc/nfsd.export/channel", O_WRONLY); > + if (fd < 0) > + return 0; > + n = exportfs_write(fd, buf, strlen(buf)); > + close(fd); > + if (n < 0) > + return 0; > + return 1; > +} > + > /* > * Create a pseudo export > */ > @@ -82,6 +116,7 @@ v4root_create(char *path, nfs_export *export) > nfs_export *exp; > struct exportent eep; > struct exportent *curexp = &export->m_export; > + char uuid[33]; > > dupexportent(&eep, &pseudo_root.m_export); > eep.e_ttl = default_ttl; > @@ -89,6 +124,28 @@ v4root_create(char *path, nfs_export *export) > strncpy(eep.e_path, path, sizeof(eep.e_path)-1); > if (strcmp(path, "/") != 0) > eep.e_flags &= ~NFSEXP_FSID; > + if (strcmp(path, "/") != 0 && > + !test_export(&eep, 0)) { > + /* Need a uuid - base it on path */ > + char buf[12], *pp = path; > + unsigned int i = 0; > + > + memset(buf, 0, sizeof(buf)); > + while (*pp) { > + buf[i] ^= *pp++; > + i += 1; > + if (i >= sizeof(buf)) > + i = 0; > + } > + memset(uuid, 'F', 32); > + uuid[32] = '\0'; > + pp = uuid + 32 - sizeof(buf) * 2; > + for (i = 0; i < sizeof(buf); i++) { > + snprintf(pp, 3, "%02X", buf[i]); > + pp += 2; > + } > + eep.e_uuid = uuid; > + } > set_pseudofs_security(&eep); > exp = export_create(&eep, 0); > if (exp == NULL) > -- > 2.31.1 > -- Chuck Lever