Hi, Jeff I wrote a POC patch, use name_to_handle_at to get nfs root filehandle instead of /proc/fs/nfsd/filehandle. I did some simple tests and it works. Pls check the POC patch below: --- support/export/cache.c | 95 +++++++++++++++++++++++++++++++++++++++++- 1 file changed, 93 insertions(+), 2 deletions(-) diff --git a/support/export/cache.c b/support/export/cache.c index 6c0a44a3..adecac2e 100644 --- a/support/export/cache.c +++ b/support/export/cache.c @@ -43,6 +43,25 @@ #include "blkid/blkid.h" #endif +#define NFS4_FHSIZE 128 + +struct knfsd_fh { + unsigned int fh_size; /* + * Points to the current size while + * building a new file handle. + */ + union { + char fh_raw[NFS4_FHSIZE]; + struct { + uint8_t fh_version; /* == 1 */ + uint8_t fh_auth_type; /* deprecated */ + uint8_t fh_fsid_type; + uint8_t fh_fileid_type; + uint32_t fh_fsid[]; /* flexible-array member */ + }; + }; +}; + enum nfsd_fsid { FSID_DEV = 0, FSID_NUM, @@ -1827,8 +1846,8 @@ int cache_export(nfs_export *exp, char *path) * read filehandle <&0 * } <> /proc/fs/nfsd/filehandle */ -struct nfs_fh_len * -cache_get_filehandle(nfs_export *exp, int len, char *p) +static struct nfs_fh_len * +cache_get_filehandle_by_proc(nfs_export *exp, int len, char *p) { static struct nfs_fh_len fh; char buf[RPC_CHAN_BUF_SIZE], *bp; @@ -1862,6 +1881,78 @@ cache_get_filehandle(nfs_export *exp, int len, char *p) return &fh; } +static struct nfs_fh_len * +cache_get_filehandle_by_name(nfs_export *exp, char *name) +{ + static struct nfs_fh_len fh; + struct { + struct file_handle fh; + unsigned char handle[128]; + } file_fh; + char buf[RPC_CHAN_BUF_SIZE] = {0}; + char *mesg = buf; + int len, mnt_id; + unsigned int e_fsid; + struct knfsd_fh kfh; + char u[16]; + + memset(fh.fh_handle, 0, sizeof(fh.fh_handle)); + + file_fh.fh.handle_bytes = 128; + if (name_to_handle_at(AT_FDCWD, name, &file_fh.fh, &mnt_id, 0) < 0) + return NULL; + + memset(fh.fh_handle, 0, sizeof(fh.fh_handle)); + memset(&kfh, 0, sizeof(struct knfsd_fh)); + kfh.fh_version = 1; + kfh.fh_auth_type = 0; + e_fsid = exp->m_export.e_fsid; + + if (e_fsid > 0) { + len = 12; + fh.fh_size = 8; + kfh.fh_size = 12; + kfh.fh_fsid_type = 1; + kfh.fh_fsid[0] = e_fsid; + } else { + len = file_fh.fh.handle_bytes + 8; + fh.fh_size = file_fh.fh.handle_bytes; + kfh.fh_size = file_fh.fh.handle_bytes + sizeof(kfh.fh_size); + kfh.fh_fsid_type = FSID_UUID16_INUM; + if (file_fh.fh.handle_bytes <= 12) { + kfh.fh_fsid[0] = *(uint32_t *)file_fh.fh.f_handle; + kfh.fh_fsid[1] = 0; + } else { + kfh.fh_fsid[0] = *(uint32_t *)file_fh.fh.f_handle; + kfh.fh_fsid[1] = *((uint32_t *)file_fh.fh.f_handle + 1); + } + } + kfh.fh_fileid_type = 0; // FILEID_ROOT + + qword_addhex(&mesg, &len, kfh.fh_raw, kfh.fh_size); + mesg = buf; + len = qword_get(&mesg, (char *)fh.fh_handle, NFS3_FHSIZE); + if (e_fsid == 0) { + len = 16; + uuid_by_path(name, 0, 16, u); + memcpy((char *)fh.fh_handle+12, u, 16); + fh.fh_size += 16; + } + + return &fh; +} + +struct nfs_fh_len * +cache_get_filehandle(nfs_export *exp, int len, char *p) +{ + struct nfs_fh_len *fh; + fh = cache_get_filehandle_by_name(exp, p); + if (!fh) + fh = cache_get_filehandle_by_proc(exp, len, p); + + return fh; +} + /* Wait for all worker child processes to exit and reap them */ void cache_wait_for_workers(char *prog) -- 2.39.1