diff mbox series

[2/2] btrfs-progs: read fsid from the sysfs in device_is_seed

Message ID 7523436ccbf95d7fde690f41095637ce9d9fc1b4.1676124188.git.anand.jain@oracle.com (mailing list archive)
State New, archived
Headers show
Series btrfs-progs: read device fsid from the sysfs | expand

Commit Message

Anand Jain Feb. 13, 2023, 9:37 a.m. UTC
The kernel commit a26d60dedf9a ("btrfs: sysfs: add devinfo/fsid to
retrieve actual fsid from the device" introduced a sysfs interface
to access the device's fsid from the kernel. This is a more
reliable method to obtain the fsid compared to reading the
superblock, and it even works if the device is not present.
Additionally, this sysfs interface can be read by non-root users.

Therefore, it is recommended to utilize this new sysfs interface to
retrieve the fsid.

Reviewed-by: Josef Bacik <josef@toxicpanda.com>
Signed-off-by: Anand Jain <anand.jain@oracle.com>
---
 cmds/filesystem-usage.c | 38 ++++++++++++++++++++++++++++++--------
 1 file changed, 30 insertions(+), 8 deletions(-)

Comments

David Sterba Feb. 21, 2023, 11:17 p.m. UTC | #1
On Mon, Feb 13, 2023 at 05:37:42PM +0800, Anand Jain wrote:
> The kernel commit a26d60dedf9a ("btrfs: sysfs: add devinfo/fsid to
> retrieve actual fsid from the device" introduced a sysfs interface
> to access the device's fsid from the kernel. This is a more
> reliable method to obtain the fsid compared to reading the
> superblock, and it even works if the device is not present.
> Additionally, this sysfs interface can be read by non-root users.
> 
> Therefore, it is recommended to utilize this new sysfs interface to
> retrieve the fsid.
> 
> Reviewed-by: Josef Bacik <josef@toxicpanda.com>
> Signed-off-by: Anand Jain <anand.jain@oracle.com>
> ---
>  cmds/filesystem-usage.c | 38 ++++++++++++++++++++++++++++++--------
>  1 file changed, 30 insertions(+), 8 deletions(-)
> 
> diff --git a/cmds/filesystem-usage.c b/cmds/filesystem-usage.c
> index bef9a1129a63..e7fa18dc82dc 100644
> --- a/cmds/filesystem-usage.c
> +++ b/cmds/filesystem-usage.c
> @@ -39,6 +39,7 @@
>  #include "common/help.h"
>  #include "common/device-utils.h"
>  #include "common/messages.h"
> +#include "common/path-utils.h"
>  #include "cmds/filesystem-usage.h"
>  #include "cmds/commands.h"
>  
> @@ -701,14 +702,33 @@ out:
>  	return ret;
>  }
>  
> -static int device_is_seed(const char *dev_path, u8 *mnt_fsid)
> +static int device_is_seed(int fd, const char *dev_path, u64 devid, u8 *mnt_fsid)
>  {
> +	char fsidparse[BTRFS_UUID_UNPARSED_SIZE];
> +	char fsid_path[PATH_MAX];
> +	char devid_str[20];
>  	uuid_t fsid;
> -	int ret;
> +	int ret = -1;
> +	int sysfs_fd;
> +
> +	snprintf(devid_str, 20, "%llu", devid);
> +	/* devinfo/<devid>/fsid */
> +	path_cat3_out(fsid_path, "devinfo", devid_str, "fsid");

This could potentially fail so the return value needs to be checked.

> +
> +	/* /sys/fs/btrfs/<fsid>/devinfo/<devid>/fsid */
> +	sysfs_fd = sysfs_open_fsid_file(fd, fsid_path);
> +	if (sysfs_fd >= 0) {
> +		sysfs_read_file(sysfs_fd, fsidparse, BTRFS_UUID_UNPARSED_SIZE);
> +		fsidparse[BTRFS_UUID_UNPARSED_SIZE - 1] = 0;
> +		ret = uuid_parse(fsidparse, fsid);
> +		close(sysfs_fd);
> +	}
>  
> -	ret = dev_to_fsid(dev_path, fsid);
> -	if (ret)
> -		return ret;
> +	if (ret) {
> +		ret = dev_to_fsid(dev_path, fsid);
> +		if (ret)
> +			return ret;
> +	}
diff mbox series

Patch

diff --git a/cmds/filesystem-usage.c b/cmds/filesystem-usage.c
index bef9a1129a63..e7fa18dc82dc 100644
--- a/cmds/filesystem-usage.c
+++ b/cmds/filesystem-usage.c
@@ -39,6 +39,7 @@ 
 #include "common/help.h"
 #include "common/device-utils.h"
 #include "common/messages.h"
+#include "common/path-utils.h"
 #include "cmds/filesystem-usage.h"
 #include "cmds/commands.h"
 
@@ -701,14 +702,33 @@  out:
 	return ret;
 }
 
-static int device_is_seed(const char *dev_path, u8 *mnt_fsid)
+static int device_is_seed(int fd, const char *dev_path, u64 devid, u8 *mnt_fsid)
 {
+	char fsidparse[BTRFS_UUID_UNPARSED_SIZE];
+	char fsid_path[PATH_MAX];
+	char devid_str[20];
 	uuid_t fsid;
-	int ret;
+	int ret = -1;
+	int sysfs_fd;
+
+	snprintf(devid_str, 20, "%llu", devid);
+	/* devinfo/<devid>/fsid */
+	path_cat3_out(fsid_path, "devinfo", devid_str, "fsid");
+
+	/* /sys/fs/btrfs/<fsid>/devinfo/<devid>/fsid */
+	sysfs_fd = sysfs_open_fsid_file(fd, fsid_path);
+	if (sysfs_fd >= 0) {
+		sysfs_read_file(sysfs_fd, fsidparse, BTRFS_UUID_UNPARSED_SIZE);
+		fsidparse[BTRFS_UUID_UNPARSED_SIZE - 1] = 0;
+		ret = uuid_parse(fsidparse, fsid);
+		close(sysfs_fd);
+	}
 
-	ret = dev_to_fsid(dev_path, fsid);
-	if (ret)
-		return ret;
+	if (ret) {
+		ret = dev_to_fsid(dev_path, fsid);
+		if (ret)
+			return ret;
+	}
 
 	if (memcmp(mnt_fsid, fsid, BTRFS_FSID_SIZE))
 		return 0;
@@ -763,13 +783,15 @@  static int load_device_info(int fd, struct device_info **devinfo_ret,
 		}
 
 		/*
-		 * Skip seed device by checking device's fsid (requires root).
-		 * And we will skip only if dev_to_fsid is successful and dev
+		 * Skip seed device by checking device's fsid (requires root if
+		 * kernel is not patched to provide fsid from the sysfs).
+		 * And we will skip only if device_is_seed is successful and dev
 		 * is a seed device.
 		 * Ignore any other error including -EACCES, which is seen when
 		 * a non-root process calls dev_to_fsid(path)->open(path).
 		 */
-		ret = device_is_seed((const char *)dev_info.path, fi_args.fsid);
+		ret = device_is_seed(fd, (const char *)dev_info.path, i,
+				     fi_args.fsid);
 		if (!ret)
 			continue;