diff mbox series

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

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

Commit Message

黄佳男 Feb. 29, 2024, 7:41 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>
---
v2:
- Remove use of LOOP_GET_STATUS64.
 lib/libf2fs.c | 41 ++++++++++++++++++++++++++++-------------
 1 file changed, 28 insertions(+), 13 deletions(-)
diff mbox series

Patch

diff --git a/lib/libf2fs.c b/lib/libf2fs.c
index d51e485..92faff9 100644
--- a/lib/libf2fs.c
+++ b/lib/libf2fs.c
@@ -832,7 +832,7 @@  int f2fs_dev_is_umounted(char *path)
 		}
 	} else if (S_ISREG(st_buf.st_mode)) {
 		/* check whether regular is backfile of loop device */
-#if defined(HAVE_LINUX_LOOP_H) && defined(HAVE_LINUX_MAJOR_H)
+#if defined(HAVE_LINUX_MAJOR_H)
 		struct mntent *mnt;
 		struct stat st_loop;
 		FILE *f;
@@ -840,8 +840,9 @@  int f2fs_dev_is_umounted(char *path)
 		f = setmntent("/proc/mounts", "r");
 
 		while ((mnt = getmntent(f)) != NULL) {
-			struct loop_info64 loopinfo = {0, };
-			int loop_fd, err;
+			struct stat st_back;
+			int sysfs_fd, rc;
+			char buf[PATH_MAX + 1];
 
 			if (mnt->mnt_fsname[0] != '/')
 				continue;
@@ -852,23 +853,37 @@  int f2fs_dev_is_umounted(char *path)
 			if (major(st_loop.st_rdev) != LOOP_MAJOR)
 				continue;
 
-			loop_fd = open(mnt->mnt_fsname, O_RDONLY);
-			if (loop_fd < 0) {
+			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",
-					mnt->mnt_fsname, errno);
+					buf, errno);
 				return -1;
 			}
 
-			err = ioctl(loop_fd, LOOP_GET_STATUS64, &loopinfo);
-			close(loop_fd);
-			if (err < 0) {
-				MSG(0, "\tError: ioctl LOOP_GET_STATUS64 failed errno:%d!\n",
-					errno);
+			memset(buf, 0, PATH_MAX + 1);
+			rc = read(sysfs_fd, buf, PATH_MAX);
+			if (rc < 0) {
+				MSG(0, "Info: read %s failed errno:%d\n",
+					buf, errno);
+				return -1;
+			}
+
+			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 == loopinfo.lo_device &&
-				st_buf.st_ino == loopinfo.lo_inode) {
+			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;
 			}