Hi, > On Mon, 21 Jun 2021, Wang Yugui wrote: > > Hi, > > > > > > > It seems more fixes are needed. > > > > > > > > I think the problem is that the submount doesn't appear in /proc/mounts. > > > > "nfsd_fh()" in nfs-utils needs to be able to map from the uuid for a > > > > filesystem to the mount point. To do this it walks through /proc/mounts > > > > checking the uuid of each filesystem. If a filesystem isn't listed > > > > there, it obviously fails. > > > > > > > > I guess you could add code to nfs-utils to do whatever "btrfs subvol > > > > list" does to make up for the fact that btrfs doesn't register in > > > > /proc/mounts. > > > > > > Another approach might be to just change svcxdr_encode_fattr3() and > > > nfsd4_encode_fattr() in the 'FSIDSOJURCE_UUID' case to check if > > > dentry->d_inode has a different btrfs volume id to > > > exp->ex_path.dentry->d_inode. > > > If it does, then mix the volume id into the fsid somehow. > > > > > > With that, you wouldn't want the first change I suggested. > > > > This is what I have done. and it is based on linux 5.10.44 > > > > but it still not work, so still more jobs needed. > > > > The following is more what I had in mind. It doesn't quite work and I > cannot work out why. > > If you 'stat' a file inside the subvol, then 'find' will not complete. > If you don't, then it will. > > Doing that 'stat' changes the st_dev number of the main filesystem, > which seems really weird. > I'm probably missing something obvious. Maybe a more careful analysis > of what is changing when will help. we compare the trace output between crossmnt and btrfs subvol with some trace, we found out that we need to add the subvol support to follow_down(). btrfs subvol should be treated as virtual 'mount point' for nfsd in follow_down(). Best Regards Wang Yugui (wangyugui@xxxxxxxxxxxx) 2021/06/22 > NeilBrown > > > diff --git a/fs/nfsd/export.c b/fs/nfsd/export.c > index 9421dae22737..790a3357525d 100644 > --- a/fs/nfsd/export.c > +++ b/fs/nfsd/export.c > @@ -15,6 +15,7 @@ > #include <linux/slab.h> > #include <linux/namei.h> > #include <linux/module.h> > +#include <linux/statfs.h> > #include <linux/exportfs.h> > #include <linux/sunrpc/svc_xprt.h> > > @@ -575,6 +576,7 @@ static int svc_export_parse(struct cache_detail *cd, char *mesg, int mlen) > int err; > struct auth_domain *dom = NULL; > struct svc_export exp = {}, *expp; > + struct kstatfs statfs; > int an_int; > > if (mesg[mlen-1] != '\n') > @@ -604,6 +606,10 @@ static int svc_export_parse(struct cache_detail *cd, char *mesg, int mlen) > err = kern_path(buf, 0, &exp.ex_path); > if (err) > goto out1; > + err = vfs_statfs(&exp.ex_path, &statfs); > + if (err) > + goto out3; > + exp.ex_fsid64 = statfs.f_fsid; > > exp.ex_client = dom; > exp.cd = cd; > @@ -809,6 +815,7 @@ static void export_update(struct cache_head *cnew, struct cache_head *citem) > new->ex_anon_uid = item->ex_anon_uid; > new->ex_anon_gid = item->ex_anon_gid; > new->ex_fsid = item->ex_fsid; > + new->ex_fsid64 = item->ex_fsid64; > new->ex_devid_map = item->ex_devid_map; > item->ex_devid_map = NULL; > new->ex_uuid = item->ex_uuid; > diff --git a/fs/nfsd/export.h b/fs/nfsd/export.h > index ee0e3aba4a6e..d3eb9a599918 100644 > --- a/fs/nfsd/export.h > +++ b/fs/nfsd/export.h > @@ -68,6 +68,7 @@ struct svc_export { > kuid_t ex_anon_uid; > kgid_t ex_anon_gid; > int ex_fsid; > + __kernel_fsid_t ex_fsid64; > unsigned char * ex_uuid; /* 16 byte fsid */ > struct nfsd4_fs_locations ex_fslocs; > uint32_t ex_nflavors; > diff --git a/fs/nfsd/nfs4xdr.c b/fs/nfsd/nfs4xdr.c > index 7abeccb975b2..8144e6037eae 100644 > --- a/fs/nfsd/nfs4xdr.c > +++ b/fs/nfsd/nfs4xdr.c > @@ -2869,6 +2869,7 @@ nfsd4_encode_fattr(struct xdr_stream *xdr, struct svc_fh *fhp, > if (err) > goto out_nfserr; > if ((bmval0 & (FATTR4_WORD0_FILES_AVAIL | FATTR4_WORD0_FILES_FREE | > + FATTR4_WORD0_FSID | > FATTR4_WORD0_FILES_TOTAL | FATTR4_WORD0_MAXNAME)) || > (bmval1 & (FATTR4_WORD1_SPACE_AVAIL | FATTR4_WORD1_SPACE_FREE | > FATTR4_WORD1_SPACE_TOTAL))) { > @@ -3024,6 +3025,12 @@ nfsd4_encode_fattr(struct xdr_stream *xdr, struct svc_fh *fhp, > case FSIDSOURCE_UUID: > p = xdr_encode_opaque_fixed(p, exp->ex_uuid, > EX_UUID_LEN); > + if (statfs.f_fsid.val[0] != exp->ex_fsid64.val[0] || > + statfs.f_fsid.val[1] != exp->ex_fsid64.val[1]) { > + /* looks like a btrfs subvol */ > + p[-2] ^= statfs.f_fsid.val[0]; > + p[-1] ^= statfs.f_fsid.val[1]; > + } > break; > } > }
Attachment:
0001-nfsd-btrfs-subvol-support.txt
Description: Binary data
Attachment:
0002-trace-nfsd-btrfs-subvol-support.txt
Description: Binary data