public inbox for linux-nfs@vger.kernel.org
 help / color / mirror / Atom feed
From: Wang Yugui <wangyugui@e16-tech.com>
To: "NeilBrown" <neilb@suse.de>
Cc: linux-nfs@vger.kernel.org
Subject: Re: any idea about auto export multiple btrfs snapshots?
Date: Mon, 21 Jun 2021 16:34:41 +0800	[thread overview]
Message-ID: <20210621163441.428C.409509F4@e16-tech.com> (raw)
In-Reply-To: <162425240757.17441.3695249639927377778@noble.neil.brown.name>

[-- Attachment #1: Type: text/plain, Size: 1065 bytes --]

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.

Best Regards
Wang Yugui (wangyugui@e16-tech.com)
2021/06/21


[-- Attachment #2: 0001-nfsd-btrfs-subvol-support.patch --]
[-- Type: application/octet-stream, Size: 4741 bytes --]

From 57e6b3cec9b8ac396b661c190511af80839ddbe5 Mon Sep 17 00:00:00 2001
From: wangyugui <wangyugui@e16-tech.com>
Date: Thu, 17 Jun 2021 08:33:06 +0800
Subject: [PATCH] nfsd: btrfs subvol support

(struct statfs).f_fsid: 	uniq between btrfs subvols
(struct stat).st_dev: 		uniq between btrfs subvols
(struct statx).stx_mnt_id:	NOT uniq between btrfs subvols, but yet not used in nfs/nfsd
	kernel samples/vfs/test-statx.c
		stx_rdev_major/stx_rdev_minor seems be truncated by something
		like old_encode_dev()/old_decode_dev()?

TODO: (struct nfs_fattr).fsid
TODO: FSIDSOURCE_FSID in nfs3xdr.c/nfsxdr.c
---
 fs/namei.c         |  2 ++
 fs/nfsd/nfs3xdr.c  |  2 +-
 fs/nfsd/nfs4xdr.c  | 10 ++++++++--
 fs/nfsd/vfs.c      |  6 ++++++
 include/linux/fs.h | 13 +++++++++++++
 5 files changed, 30 insertions(+), 3 deletions(-)

diff --git a/fs/namei.c b/fs/namei.c
index fe132e3..6974a95 100644
--- a/fs/namei.c
+++ b/fs/namei.c
@@ -1105,6 +1105,8 @@ int follow_up(struct path *path)
 	struct mount *parent;
 	struct dentry *mountpoint;
 
+	if(unlikely(d_is_btrfs_subvol(path->dentry)))
+		return 0;
 	read_seqlock_excl(&mount_lock);
 	parent = mnt->mnt_parent;
 	if (parent == mnt) {
diff --git a/fs/nfsd/nfs3xdr.c b/fs/nfsd/nfs3xdr.c
index 716566d..45666b3 100644
--- a/fs/nfsd/nfs3xdr.c
+++ b/fs/nfsd/nfs3xdr.c
@@ -877,7 +877,7 @@ compose_entry_fh(struct nfsd3_readdirres *cd, struct svc_fh *fhp,
 		dchild = lookup_positive_unlocked(name, dparent, namlen);
 	if (IS_ERR(dchild))
 		return rv;
-	if (d_mountpoint(dchild))
+	if (d_mountpoint(dchild) || unlikely(d_is_btrfs_subvol(dchild)))
 		goto out;
 	if (dchild->d_inode->i_ino != ino)
 		goto out;
diff --git a/fs/nfsd/nfs4xdr.c b/fs/nfsd/nfs4xdr.c
index 5f5169b..939d095 100644
--- a/fs/nfsd/nfs4xdr.c
+++ b/fs/nfsd/nfs4xdr.c
@@ -2728,6 +2728,7 @@ nfsd4_encode_fattr(struct xdr_stream *xdr, struct svc_fh *fhp,
 		.dentry	= dentry,
 	};
 	struct nfsd_net *nn = net_generic(SVC_NET(rqstp), nfsd_net_id);
+	bool is_btrfs_subvol= d_is_btrfs_subvol(dentry);
 
 	BUG_ON(bmval1 & NFSD_WRITEONLY_ATTRS_WORD1);
 	BUG_ON(!nfsd_attrs_supported(minorversion, bmval));
@@ -2744,7 +2745,8 @@ nfsd4_encode_fattr(struct xdr_stream *xdr, struct svc_fh *fhp,
 	if ((bmval0 & (FATTR4_WORD0_FILES_AVAIL | FATTR4_WORD0_FILES_FREE |
 			FATTR4_WORD0_FILES_TOTAL | FATTR4_WORD0_MAXNAME)) ||
 	    (bmval1 & (FATTR4_WORD1_SPACE_AVAIL | FATTR4_WORD1_SPACE_FREE |
-		       FATTR4_WORD1_SPACE_TOTAL))) {
+		       FATTR4_WORD1_SPACE_TOTAL)) ||
+		unlikely(is_btrfs_subvol)) {
 		err = vfs_statfs(&path, &statfs);
 		if (err)
 			goto out_nfserr;
@@ -2885,7 +2887,11 @@ nfsd4_encode_fattr(struct xdr_stream *xdr, struct svc_fh *fhp,
 			p = xdr_encode_hyper(p, NFS4_REFERRAL_FSID_MINOR);
 		} else switch(fsid_source(fhp)) {
 		case FSIDSOURCE_FSID:
-			p = xdr_encode_hyper(p, (u64)exp->ex_fsid);
+			if (unlikely(is_btrfs_subvol)){
+				*p++ = cpu_to_be32(statfs.f_fsid.val[0]);
+				*p++ = cpu_to_be32(statfs.f_fsid.val[1]);
+			} else
+				p = xdr_encode_hyper(p, (u64)exp->ex_fsid);
 			p = xdr_encode_hyper(p, (u64)0);
 			break;
 		case FSIDSOURCE_DEV:
diff --git a/fs/nfsd/vfs.c b/fs/nfsd/vfs.c
index 1ecacee..ae34ffc 100644
--- a/fs/nfsd/vfs.c
+++ b/fs/nfsd/vfs.c
@@ -68,6 +68,10 @@ nfsd_cross_mnt(struct svc_rqst *rqstp, struct dentry **dpp,
 	err = follow_down(&path);
 	if (err < 0)
 		goto out;
+	if (unlikely(d_is_btrfs_subvol(dentry))){
+		path_put(&path);
+		goto out;
+	} else
 	if (path.mnt == exp->ex_path.mnt && path.dentry == dentry &&
 	    nfsd_mountpoint(dentry, exp) == 2) {
 		/* This is only a mountpoint in some other namespace */
@@ -160,6 +164,8 @@ int nfsd_mountpoint(struct dentry *dentry, struct svc_export *exp)
 		return 1;
 	if (nfsd4_is_junction(dentry))
 		return 1;
+	if (d_is_btrfs_subvol(dentry))
+		return 1;
 	if (d_mountpoint(dentry))
 		/*
 		 * Might only be a mountpoint in a different namespace,
diff --git a/include/linux/fs.h b/include/linux/fs.h
index 8bde32c..b0d52e9 100644
--- a/include/linux/fs.h
+++ b/include/linux/fs.h
@@ -3399,6 +3399,19 @@ static inline bool is_root_inode(struct inode *inode)
 	return inode == inode->i_sb->s_root->d_inode;
 }
 
+/*
+ * same logical as fs/btrfs is_subvolume_inode(struct inode *inode)
+ * #define BTRFS_FIRST_FREE_OBJECTID 256ULL
+ * #define BTRFS_SUPER_MAGIC       0x9123683E
+ */
+static inline bool d_is_btrfs_subvol(const struct dentry *dentry)
+{
+    bool ret = dentry->d_inode && unlikely(dentry->d_inode->i_ino == 256ULL) &&
+		dentry->d_sb && dentry->d_sb->s_magic == 0x9123683E;
+	//printk(KERN_INFO "d_is_btrfs_subvol(%s)=%d\n", dentry->d_name.name, ret);
+	return ret;
+}
+
 static inline bool dir_emit(struct dir_context *ctx,
 			    const char *name, int namelen,
 			    u64 ino, unsigned type)
-- 
2.30.2


[-- Attachment #3: 0002-trace-nfsd-btrfs-subvol-support.txt --]
[-- Type: application/octet-stream, Size: 3431 bytes --]

From 6e709554e4c7d5efd3b030fc08b6e6493879a025 Mon Sep 17 00:00:00 2001
From: wangyugui <wangyugui@e16-tech.com>
Date: Thu, 17 Jun 2021 08:33:06 +0800
Subject: [PATCH] trace nfsd: btrfs subvol support

[  268.994169] follow_down(xfs2)=0
[  268.997405] nfsd_cross_mnt(xfs2)=0
*[  269.000840] nfsd4_encode_dirent_fattr(/) ignore_crossmnt=0
	why /
*[  269.006477] nfs_d_automount(xfs2)
	why not happen when btrfs subvol
[  269.009892] follow_down(xfs2)=0
[  269.013055] nfsd_cross_mnt(xfs2)=0

[  483.037221] follow_down(sub1)=0
[  483.040428] nfsd_cross_mnt(sub1)=0
[  483.043855] nfsd4_encode_dirent_fattr(sub1) ignore_crossmnt=0
[  483.049635] nfsd4_encode_dirent_fattr(.snapshot) ignore_crossmnt=0
[  483.055847] nfsd4_encode_dirent_fattr(dir1) ignore_crossmnt=0
[  483.062669] follow_down(sub2)=0
[  483.066800] nfsd_cross_mnt(sub2)=0

btrfs subvols =>force crossmnt
	subvol nfs/umount: os shutdonw or manual nfs/umount?
		special status(BTRFS_LAST_FREE_OBJECTID,only return to nfs)?
		#define BTRFS_LAST_FREE_OBJECTID -256ULL
		(struct file )->(struct inode *f_inode)->(struct super_block *i_sb;)->(unsigned long s_magic)
btrfs->xfs	=>still need crossmnt
xfs->btrfs	=>still need crossmnt

NFSEXP_CROSSMOUNT
NFSD_JUNCTION_XATTR_NAME
AT_NO_AUTOMOUNT
NFS_ATTR_FATTR_MOUNTPOINT
S_AUTOMOUNT

---
 fs/nfs/dir.c       | 2 ++
 fs/nfs/namespace.c | 1 +
 fs/nfsd/nfs4xdr.c  | 3 +++
 fs/nfsd/vfs.c      | 1 +
 4 files changed, 7 insertions(+)

diff --git a/fs/nfs/dir.c b/fs/nfs/dir.c
index c837675..975440d 100644
--- a/fs/nfs/dir.c
+++ b/fs/nfs/dir.c
@@ -1799,6 +1799,8 @@ nfs4_do_lookup_revalidate(struct inode *dir, struct dentry *dentry,
 
 	if (!(flags & LOOKUP_OPEN) || (flags & LOOKUP_DIRECTORY))
 		goto full_reval;
+	if (dentry->d_inode && dentry->d_inode->i_ino == 256ULL && dentry->d_sb)
+		printk(KERN_INFO "nfs4_do_lookup_revalidate(%s)=%lx\n", dentry->d_name.name, dentry->d_sb->s_magic);
 	if (d_mountpoint(dentry))
 		goto full_reval;
 
diff --git a/fs/nfs/namespace.c b/fs/nfs/namespace.c
index 2bcbe38..f69715c 100644
--- a/fs/nfs/namespace.c
+++ b/fs/nfs/namespace.c
@@ -152,6 +152,7 @@ struct vfsmount *nfs_d_automount(struct path *path)
 	int timeout = READ_ONCE(nfs_mountpoint_expiry_timeout);
 	int ret;
 
+	printk(KERN_INFO "nfs_d_automount(%s)\n", path->dentry->d_name.name);
 	if (IS_ROOT(path->dentry))
 		return ERR_PTR(-ESTALE);
 
diff --git a/fs/nfsd/nfs4xdr.c b/fs/nfsd/nfs4xdr.c
index 939d095..cb5b328 100644
--- a/fs/nfsd/nfs4xdr.c
+++ b/fs/nfsd/nfs4xdr.c
@@ -3316,6 +3316,8 @@ nfsd4_encode_dirent_fattr(struct xdr_stream *xdr, struct nfsd4_readdir *cd,
 	 */
 	if (nfsd_mountpoint(dentry, exp)) {
 		int err;
+		// if(d_is_btrfs_subvol(dentry))
+		//	cd->rd_bmval[1] |= FATTR4_WORD1_MOUNTED_ON_FILEID;
 
 		if (!(exp->ex_flags & NFSEXP_V4ROOT)
 				&& !attributes_need_mount(cd->rd_bmval)) {
@@ -3343,6 +3345,7 @@ nfsd4_encode_dirent_fattr(struct xdr_stream *xdr, struct nfsd4_readdir *cd,
 out_put:
 	dput(dentry);
 	exp_put(exp);
+	printk(KERN_INFO "nfsd4_encode_dirent_fattr(%s) ignore_crossmnt=%d\n", dentry->d_name.name, ignore_crossmnt);
 	return nfserr;
 }
 
diff --git a/fs/nfsd/vfs.c b/fs/nfsd/vfs.c
index ae34ffc..c12a394 100644
--- a/fs/nfsd/vfs.c
+++ b/fs/nfsd/vfs.c
@@ -111,6 +111,7 @@ nfsd_cross_mnt(struct svc_rqst *rqstp, struct dentry **dpp,
 	path_put(&path);
 	exp_put(exp2);
 out:
+	printk(KERN_INFO "nfsd_cross_mnt(%s)=%d\n", dentry->d_name.name, err);
 	return err;
 }
 
-- 
2.30.2


  reply	other threads:[~2021-06-21  8:34 UTC|newest]

Thread overview: 60+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2021-06-13  3:53 any idea about auto export multiple btrfs snapshots? Wang Yugui
2021-06-14 22:50 ` NeilBrown
2021-06-15 15:13   ` Wang Yugui
2021-06-15 15:41     ` Wang Yugui
2021-06-16  5:47     ` Wang Yugui
2021-06-17  3:02     ` NeilBrown
2021-06-17  4:28       ` Wang Yugui
2021-06-18  0:32         ` NeilBrown
2021-06-18  7:26           ` Wang Yugui
2021-06-18 13:34             ` Wang Yugui
2021-06-19  6:47               ` Wang Yugui
2021-06-20 12:27             ` Wang Yugui
2021-06-21  4:52             ` NeilBrown
2021-06-21  5:13               ` NeilBrown
2021-06-21  8:34                 ` Wang Yugui [this message]
2021-06-22  1:28                   ` NeilBrown
2021-06-22  3:22                     ` Wang Yugui
2021-06-22  7:14                       ` Wang Yugui
2021-06-23  0:59                         ` NeilBrown
2021-06-23  6:14                           ` Wang Yugui
2021-06-23  6:29                             ` NeilBrown
2021-06-23  9:34                               ` Wang Yugui
2021-06-23 23:38                                 ` NeilBrown
2021-06-23 15:35                           ` J. Bruce Fields
2021-06-23 22:04                             ` NeilBrown
2021-06-23 22:25                               ` J. Bruce Fields
2021-06-23 23:29                                 ` NeilBrown
2021-06-23 23:41                                   ` Frank Filz
2021-06-24  0:01                                   ` J. Bruce Fields
2021-06-24 21:58                               ` Patrick Goetz
2021-06-24 23:27                                 ` NeilBrown
2021-06-21 14:35               ` Frank Filz
2021-06-21 14:55                 ` Wang Yugui
2021-06-21 17:49                   ` Frank Filz
2021-06-21 22:41                     ` Wang Yugui
2021-06-22 17:34                       ` Frank Filz
2021-06-22 22:48                         ` Wang Yugui
2021-06-17  2:15   ` Wang Yugui
     [not found] ` <20210310074620.GA2158@tik.uni-stuttgart.de>
     [not found]   ` <162632387205.13764.6196748476850020429@noble.neil.brown.name>
2021-07-15 14:09     ` [PATCH/RFC] NFSD: handle BTRFS subvolumes better Josef Bacik
2021-07-15 16:45       ` Christoph Hellwig
2021-07-15 17:11         ` Josef Bacik
2021-07-15 17:24           ` Christoph Hellwig
2021-07-15 18:01             ` Josef Bacik
2021-07-15 22:37               ` NeilBrown
2021-07-19 15:40                 ` Josef Bacik
2021-07-19 20:00                   ` J. Bruce Fields
2021-07-19 20:44                     ` Josef Bacik
2021-07-19 23:53                       ` NeilBrown
2021-07-19 15:49                 ` J. Bruce Fields
2021-07-20  0:02                   ` NeilBrown
2021-07-19  9:16               ` Christoph Hellwig
2021-07-19 23:54                 ` NeilBrown
2021-07-20  6:23                   ` Christoph Hellwig
2021-07-20  7:17                     ` NeilBrown
2021-07-20  8:00                       ` Christoph Hellwig
2021-07-20 23:11                         ` NeilBrown
2021-07-20 22:10               ` J. Bruce Fields
2021-07-15 23:02       ` NeilBrown
2021-07-15 15:45     ` J. Bruce Fields
2021-07-15 23:08       ` NeilBrown

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20210621163441.428C.409509F4@e16-tech.com \
    --to=wangyugui@e16-tech.com \
    --cc=linux-nfs@vger.kernel.org \
    --cc=neilb@suse.de \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox