aboutsummaryrefslogtreecommitdiffstats
diff options
authorRichard Weinberger <richard@nod.at>2022-01-27 22:40:36 +0100
committerRichard Weinberger <richard@nod.at>2022-01-27 22:47:51 +0100
commit017e859dfb042293aa9eb6d34ff39d4600b4e2a8 (patch)
tree15de880841a1e18149dd2dc7f906d34999ec1d19
parentc8381a0efe17e890ebd892d573f1c3d287526245 (diff)
downloadnfs-utils-rw/reexport.tar.gz
export: Deal with NFS filesystemsrw/reexport
When a NFS filesystem is exported usually NFSD refuses to export the filesystem because mountd was unable to provide an UUID and the kernel cannot derive a dev it from the NFS client super block. To deal with this situation, teach uuid_by_path() how to generate an UUID from a NFS filesystem. Using /proc/fs/nfsfs/volumes it is possible to find the NFS fsid from the backend and use it as seed for mountd's UUID mechanism. Signed-off-by: Richard Weinberger <richard@nod.at>
-rw-r--r--support/export/cache.c65
1 files changed, 61 insertions, 4 deletions
diff --git a/support/export/cache.c b/support/export/cache.c
index a5823e92..053ad866 100644
--- a/support/export/cache.c
+++ b/support/export/cache.c
@@ -331,6 +331,51 @@ static const unsigned long nonblkid_filesystems[] = {
0 /* last */
};
+static int get_uuid_from_fsid(char *path, char *uuid_str, size_t len)
+{
+ unsigned int min_dev, maj_dev, min_fsid, maj_fsid;
+ int rc, n, found = 0, header_seen = 0;
+ struct stat stb;
+ FILE *nfsfs_fd;
+ char line[128];
+
+ rc = nfsd_path_stat(path, &stb);
+ if (rc) {
+ xlog(L_WARNING, "Unable to stat %s", path);
+ return 0;
+ }
+
+ nfsfs_fd = fopen("/proc/fs/nfsfs/volumes", "r");
+ if (nfsfs_fd == NULL) {
+ xlog(L_WARNING, "Unable to open nfsfs volume file: %m");
+ return 0;
+ }
+
+ while (fgets(line, sizeof(line), nfsfs_fd) != NULL) {
+ if (!header_seen) {
+ header_seen = 1;
+ continue;
+ }
+ n = sscanf(line, "v%*u %*x %*u %u:%u %x:%x %*s", &maj_dev,
+ &min_dev, &maj_fsid, &min_fsid);
+
+ if (n != 4) {
+ xlog(L_WARNING, "Unable to parse nfsfs volume line: %d, %s", n, line);
+ continue;
+ }
+
+ if (makedev(maj_dev, min_dev) == stb.st_dev) {
+ found = 1;
+ snprintf(uuid_str, len, "%08x%08x", maj_fsid, min_fsid);
+ break;
+ }
+ }
+
+ fclose(nfsfs_fd);
+
+ return found;
+}
+
static int uuid_by_path(char *path, int type, size_t uuidlen, char *uuid)
{
/* get a uuid for the filesystem found at 'path'.
@@ -362,7 +407,7 @@ static int uuid_by_path(char *path, int type, size_t uuidlen, char *uuid)
*/
struct statfs64 st;
char fsid_val[17];
- const char *blkid_val = NULL;
+ const char *fsuuid_val = NULL;
const char *val;
int rc;
@@ -375,7 +420,19 @@ static int uuid_by_path(char *path, int type, size_t uuidlen, char *uuid)
break;
}
if (*bad == 0)
- blkid_val = get_uuid_blkdev(path);
+ fsuuid_val = get_uuid_blkdev(path);
+ else if (*bad == 0x6969 /* NFS_SUPER_MAGIC */) {
+ char tmp[17];
+ int ret = get_uuid_from_fsid(path, tmp, sizeof(tmp));
+
+ if (ret < 0) {
+ xlog(L_WARNING, "Unable to read nfsfs volume file: %i", ret);
+ } else if (ret == 0) {
+ xlog(L_WARNING, "Unable to find nfsfs volume entry for %s", path);
+ } else {
+ fsuuid_val = tmp;
+ }
+ }
}
if (rc == 0 &&
@@ -385,8 +442,8 @@ static int uuid_by_path(char *path, int type, size_t uuidlen, char *uuid)
else
fsid_val[0] = 0;
- if (blkid_val && (type--) == 0)
- val = blkid_val;
+ if (fsuuid_val && (type--) == 0)
+ val = fsuuid_val;
else if (fsid_val[0] && (type--) == 0)
val = fsid_val;
else