diff mbox series

[f2fs-dev] f2fs-tools: fix to check loop device for non-root users

Message ID 20240229071853.62884-1-huangjianan@xiaomi.com (mailing list archive)
State Superseded
Headers show
Series [f2fs-dev] f2fs-tools: fix to check loop device for non-root users | expand

Commit Message

黄佳男 Feb. 29, 2024, 7:18 a.m. UTC
Currently mkfs/fsck gets the following error when executed by
non-root users:

Info: open /dev/loop0 failed errno:13
        Error: Not available on mounted device!

Let's fix it by reading the backing file from sysfs.

Fixes: 14197d546b93 ("f2fs-tools: fix to check loop device")
Signed-off-by: Huang Jianan <huangjianan@xiaomi.com>
---
 lib/libf2fs.c | 48 ++++++++++++++++++++++++++++++++++++++++++++++--
 1 file changed, 46 insertions(+), 2 deletions(-)
diff mbox series

Patch

diff --git a/lib/libf2fs.c b/lib/libf2fs.c
index d51e485..fa9ea9a 100644
--- a/lib/libf2fs.c
+++ b/lib/libf2fs.c
@@ -834,14 +834,20 @@  int f2fs_dev_is_umounted(char *path)
 		/* check whether regular is backfile of loop device */
 #if defined(HAVE_LINUX_LOOP_H) && defined(HAVE_LINUX_MAJOR_H)
 		struct mntent *mnt;
-		struct stat st_loop;
+		struct stat st_loop, st_sysfs;
 		FILE *f;
+		bool has_sysfs = true;
+
+		if (stat("/sys/dev/block/", &st_sysfs) || !S_ISDIR(st_sysfs.st_mode))
+			has_sysfs = false;
 
 		f = setmntent("/proc/mounts", "r");
 
 		while ((mnt = getmntent(f)) != NULL) {
 			struct loop_info64 loopinfo = {0, };
-			int loop_fd, err;
+			struct stat st_back;
+			int loop_fd, sysfs_fd, rc, err;
+			char buf[PATH_MAX + 1];
 
 			if (mnt->mnt_fsname[0] != '/')
 				continue;
@@ -852,6 +858,44 @@  int f2fs_dev_is_umounted(char *path)
 			if (major(st_loop.st_rdev) != LOOP_MAJOR)
 				continue;
 
+			if (has_sysfs) {
+				snprintf(buf, PATH_MAX,
+					 "/sys/dev/block/%d:%d/loop/backing_file",
+					 major(st_loop.st_rdev), minor(st_loop.st_rdev));
+
+				sysfs_fd = open(buf, O_RDONLY);
+				if (sysfs_fd < 0) {
+					MSG(0, "Info: open %s failed errno:%d\n",
+						buf, errno);
+					return -1;
+				}
+
+				memset(buf, 0, PATH_MAX + 1);
+				rc = read(sysfs_fd, buf, 1024);
+				if (rc < 0) {
+					MSG(0, "Info: read %s failed errno:%d\n",
+						buf, errno);
+					return -1;
+				}
+
+				/* Remove trailing newline (usual in sysfs) */
+				if (rc > 0 && *(buf + rc - 1) == '\n')
+					--rc;
+				buf[rc] = '\0';
+
+				if (stat(buf, &st_back) != 0) {
+					MSG(0, "Info: stat %s failed errno:%d\n",
+						buf, errno);
+					return -1;
+				}
+
+				if (st_buf.st_dev == st_back.st_dev &&
+					st_buf.st_ino == st_back.st_ino) {
+					MSG(0, "\tError: In use by loop device!\n");
+					return -EBUSY;
+				}
+			}
+
 			loop_fd = open(mnt->mnt_fsname, O_RDONLY);
 			if (loop_fd < 0) {
 				MSG(0, "Info: open %s failed errno:%d\n",