File util-linux-libmount-btrfs-subvolid-1.patch of Package util-linux.4136

From 618a88140e26a134727a39c906c9cdf6d0c04513 Mon Sep 17 00:00:00 2001
From: Stanislav Brabec <sbrabec@suse.cz>
Date: Wed, 27 Jan 2016 21:37:00 +0100
Subject: [PATCH 1/2] libmount: run btrfs subvol checks for "subvolid" option

It is possible to identify btrfs subvolume with "subvolid" instead of "subvol".
In such case, btrfs specific check mistakenly assumes that the default subvolume
is going to be mounted, even if subvolid specifies id of non-default subvolume.

Implement a code for "subvolid" option.

For easier review, this fix comes in two patches:
PATCH 1/2: libmount: run btrfs subvol checks for "subvolid" option
PATCH 2/2: code re-indentation

How to reproduce:
	truncate -s1G btrfs_test.img
	mkdir -p btrfs_mnt
	/sbin/mkfs.btrfs -f -d single -m single ./btrfs_test.img
	mount -o loop btrfs_test.img btrfs_mnt
	pushd .
	cd btrfs_mnt
	mkdir -p d0/dd0/ddd0
	cd d0/dd0/ddd0
	touch file{1..5}
	btrfs subvol create s1
	cd s1
	touch file{1..5}
	mkdir -p d1/dd1/ddd1
	cd d1/dd1/ddd1
	btrfs subvol create s2
	rid=$(btrfs inspect rootid s2)
	echo new default $rid
	btrfs subvol get-default .
	btrfs subvol set-default $rid .
	popd
	DEFAULT_SUBVOLID=`btrfs subvolume get-default btrfs_mnt | while read dummy id rest ; do echo $id ; done`
	NON_DEFAULT_SUBVOLID=`btrfs subvolume list btrfs_mnt | while read dummy id rest ; do if test $id = $DEFAULT_SUBVOLID ; then continue ; fi ; echo $id ; done`
	umount btrfs_mnt
	losetup /dev/loop0 $PWD/btrfs_test.img
	echo "/dev/loop0 $PWD/btrfs_mnt btrfs subvolid=$NON_DEFAULT_SUBVOLID 0 0" >>/etc/fstab
	./mount -a
	./mount -a
	umount btrfs_mnt
	sed -i "/\/dev\/loop0/d" /etc/fstab
	losetup -d /dev/loop0
	rm btrfs_test.img
	rmdir btrfs_mnt

Current behavior of second "mount -a":
    mount: /dev/loop0 is already mounted or /root/btrfs_mnt busy
           /dev/loop0 is already mounted on /root/btrfs_mnt

Signed-off-by: Stanislav Brabec <sbrabec@suse.cz>
---
 libmount/src/tab.c | 34 +++++++++++++++++++++++++++++++++-
 1 file changed, 33 insertions(+), 1 deletion(-)

Index: util-linux-2.25/libmount/src/tab.c
===================================================================
--- util-linux-2.25.orig/libmount/src/tab.c
+++ util-linux-2.25/libmount/src/tab.c
@@ -1380,6 +1380,7 @@ struct libmnt_fs *mnt_table_get_fs_root(
 
 		DBG(BTRFS, ul_debug("lookup for FS root"));
 
+		if (mnt_fs_get_option(fs, "subvolid", &vol, &volsz)) {
 		if (mnt_fs_get_option(fs, "subvol", &vol, &volsz)) {
 			/* If fstab entry does not contain "subvol", we have to
 			 * check, whether btrfs has default subvolume defined.
@@ -1407,7 +1408,7 @@ struct libmnt_fs *mnt_table_get_fs_root(
 			snprintf(default_id_str, sizeof(default_id_str), "%llu",
 					(unsigned long long int) default_id);
 
-			DBG(BTRFS, ul_debug("target=%s subvolid=%s", target, default_id_str));
+			DBG(BTRFS, ul_debug("target=%s default subvolid=%s", target, default_id_str));
 			f = mnt_table_find_target_with_option(tb, target,
 						"subvolid", default_id_str,
 						MNT_ITER_BACKWARD);
@@ -1424,6 +1425,37 @@ struct libmnt_fs *mnt_table_get_fs_root(
 				goto dflt;
 		} else
 			DBG(BTRFS, ul_debug("setting FS root: btrfs subvol"));
+		} else {
+			char *target;
+			struct libmnt_fs *f;
+			char subvolidstr[sizeof(stringify_value(UINT64_MAX))];
+
+			assert (volsz + 1 < sizeof(stringify_value(UINT64_MAX)));
+			memcpy(subvolidstr, vol, volsz);
+			subvolidstr[volsz] = '\0';
+
+			target = mnt_resolve_spec(mnt_fs_get_target(fs), tb->cache);
+			if (!target)
+				goto err;
+
+			DBG(BTRFS, ul_debug("target=%s subvolid=%s", target, subvolidstr));
+			f = mnt_table_find_target_with_option(tb, target,
+						"subvolid", subvolidstr,
+						MNT_ITER_BACKWARD);
+			if (!tb->cache)
+				free(target);
+
+			if (!f)
+				goto dflt;
+
+			/* Instead of set of BACKREF queries constructing
+			 * subvol path corresponding to a particular subvolid,
+			 * use the one in mountinfo. Kernel keeps subvol path
+			 * up to date.
+			 */
+			if (mnt_fs_get_option(f, "subvol", &vol, &volsz))
+				goto dflt;
+		}
 
 		sz = volsz;
 		if (*vol != '/')
openSUSE Build Service is sponsored by