Skip site navigation (1)Skip section navigation (2)
Date:      Sun, 4 Nov 2018 23:57:30 +0000
From:      Rick Macklem <rmacklem@uoguelph.ca>
To:        Andriy Gapon <avg@FreeBSD.org>, Julian Elischer <julian@freebsd.org>, Konstantin Belousov <kostikbel@gmail.com>
Cc:        FreeBSD Filesystems <freebsd-fs@freebsd.org>
Subject:   Re: How to fill in the fsid for file systems?
Message-ID:  <YTOPR0101MB116276DDB031C76E1F8B0560DDC90@YTOPR0101MB1162.CANPRD01.PROD.OUTLOOK.COM>
In-Reply-To: <03f24451-c0d0-0701-0e00-b2ce0f946887@FreeBSD.org>
References:  <YTOPR0101MB11620BAF0E206EE36E927A5ADDF30@YTOPR0101MB1162.CANPRD01.PROD.OUTLOOK.COM> <20181030012240.GM5335@kib.kiev.ua> <YTOPR0101MB11621427AF47133A93311E16DDCD0@YTOPR0101MB1162.CANPRD01.PROD.OUTLOOK.COM> <e7813a64-59c2-67a1-3471-b32a6ca42ef8@FreeBSD.org> <YTOPR0101MB116207BA89FB66EE9B1AAF01DDCD0@YTOPR0101MB1162.CANPRD01.PROD.OUTLOOK.COM> <a831d660-1ed9-ef21-f457-8e1e986b96f2@FreeBSD.org> <YTOPR0101MB11621C0D5F4F4D9BED169110DDCF0@YTOPR0101MB1162.CANPRD01.PROD.OUTLOOK.COM> <c98b999c-c4b8-55fe-adef-ac53e439487b@freebsd.org> <YTOPR0101MB1162A8CA4B3AAF230E73158DDDC90@YTOPR0101MB1162.CANPRD01.PROD.OUTLOOK.COM>, <03f24451-c0d0-0701-0e00-b2ce0f946887@FreeBSD.org>

index | next in thread | previous in thread | raw e-mail

[-- Attachment #1 --]
Andriy Gapon wrote:
>On 04/11/2018 17:38, Rick Macklem wrote:
>> That leaves ZFS, which is what I was asking.
>> I don't understand the ZFS code well enough to understand  what
>> dmu_objset_fsid_guid() is doing to get the fsid. I also don't know if the value
>> changes for snaphots of the same file system?
>> - If it does ever change, then that is the usage case for this option.
>
>A good ZFS example is this.
>A filesystem is duplicated using zfs send + zfs recv.  The content would be
>exactly the same (provided no modification of the source and the target after
>the duplication), but GUIDs of the source and target would be different.  The
>latter is required because the source and the target could be in the same pool.
>But even if they are in different pools (and different machines), the GUIDs
>would still be different.
Cool. Assuming the duplicated file system created via zfs send + zfs recv still
has the same fid for any given file (the stuff used by zfs_fid() stays the same
for any given file in the file system), then this would be good use case.

It will need some ZFS magic to make a generic fs mount option work for ZFS.
Maybe you can do that?

The current patch I have for adding a generic "fsid=N" mount option is in
D17839. I've also attached it to this message in case that is easier.
(It currently doesn't allow fsid=N to be used during an update "mount -u".
 This made sense to me, since an fsid shouldn't change, but if others think
  it should be changeable via "mount -u" the patch can easily be changed.)

rick
ps: I did notice the code is "slightly racy" in that there is a period of time between
      when VFS_MOUNT() sets the mnt_stat.f_fsid and when the mount structure is 
      entered in the mountlist,  where another mount could happen using the same
      mnt_stat.f_fsid value, but that has been there for a long time and wouldn't be
      easy to fix.


[-- Attachment #2 --]
--- kern/vfs_mount.c.nofsid	2018-09-29 01:13:34.523240000 -0400
+++ kern/vfs_mount.c	2018-11-04 22:49:46.614007000 -0500
@@ -110,6 +110,7 @@ static const char *global_opts[] = {
 	"rw",
 	"nosuid",
 	"noexec",
+	"fsid",
 	NULL
 };
 
@@ -838,6 +839,9 @@ vfs_domount_first(
 	struct mount *mp;
 	struct vnode *newdp;
 	int error;
+	uint64_t fsidval;
+	char *fsidstr, *fsidend;
+	int fsidlen;
 
 	ASSERT_VOP_ELOCKED(vp, __func__);
 	KASSERT((fsflags & MNT_UPDATE) == 0, ("MNT_UPDATE shouldn't be here"));
@@ -890,6 +894,28 @@ vfs_domount_first(
 	 * get.  No freeing of cn_pnbuf.
 	 */
 	error = VFS_MOUNT(mp);
+
+	/*
+	 * Set the fsid if the mount option was specified.
+	 */
+	if (error == 0) {
+		fsidlen = 0;
+		error = vfs_getopt(mp->mnt_optnew, "fsid", (void **)&fsidstr,
+		    &fsidlen);
+		if (error == 0) {
+			if (fsidlen == 0 || fsidstr[fsidlen - 1] != '\0')
+				error = EINVAL;
+			if (error == 0) {
+				fsidval = strtouq(fsidstr, &fsidend, 0);
+				if (*fsidend != '\0')
+					error = EINVAL;
+			}
+			if (error == 0)
+				error = vfs_setfsid(mp, fsidval);
+		} else
+			error = 0;
+	}
+
 	if (error != 0) {
 		vfs_unbusy(mp);
 		mp->mnt_vnodecovered = NULL;
--- kern/vfs_subr.c.nofsid	2018-09-29 02:39:27.312677000 -0400
+++ kern/vfs_subr.c	2018-11-02 20:37:40.000000000 -0400
@@ -769,6 +769,37 @@ vfs_getnewfsid(struct mount *mp)
 }
 
 /*
+ * Set the f_fsid to the argument, if possible.
+ */
+int
+vfs_setfsid(struct mount *mp, uint64_t val)
+{
+	struct mount *nmp;
+	fsid_t tfsid;
+
+	CTR2(KTR_VFS, "%s: mp %p", __func__, mp);
+	/*
+	 * Fill in the two 32bit fields of the fsid to "val".
+	 */
+	tfsid.val[0] = val;
+	tfsid.val[1] = val >> 32;
+	mtx_lock(&mntid_mtx);
+	if ((nmp = vfs_getvfs(&tfsid)) != NULL) {
+		vfs_rel(nmp);
+		mtx_unlock(&mntid_mtx);
+		if (nmp != mp)
+			return (EINVAL);
+		return (0);
+	}
+	MNT_ILOCK(mp);
+	mp->mnt_stat.f_fsid.val[0] = tfsid.val[0];
+	mp->mnt_stat.f_fsid.val[1] = tfsid.val[1];
+	MNT_IUNLOCK(mp);
+	mtx_unlock(&mntid_mtx);
+	return (0);
+}
+
+/*
  * Knob to control the precision of file timestamps:
  *
  *   0 = seconds only; nanoseconds zeroed.
--- sys/mount.h.nofsid	2018-09-29 01:13:04.659417000 -0400
+++ sys/mount.h	2018-11-03 01:06:37.854948000 -0400
@@ -918,6 +918,7 @@ void	vfs_deallocate_syncvnode(struct mount *);
 int	vfs_donmount(struct thread *td, uint64_t fsflags,
 	    struct uio *fsoptions);
 void	vfs_getnewfsid(struct mount *);
+int	vfs_setfsid(struct mount *, uint64_t);
 struct cdev *vfs_getrootfsid(struct mount *);
 struct	mount *vfs_getvfs(fsid_t *);      /* return vfs given fsid */
 struct	mount *vfs_busyfs(fsid_t *);
home | help

Want to link to this message? Use this
URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?YTOPR0101MB116276DDB031C76E1F8B0560DDC90>