diff mbox series

[f2fs-dev] f2fs-tools: fix to check loop device

Message ID 20240131073425.4043962-1-chao@kernel.org (mailing list archive)
State New
Headers show
Series [f2fs-dev] f2fs-tools: fix to check loop device | expand

Commit Message

Chao Yu Jan. 31, 2024, 7:34 a.m. UTC
Otherwise, mkfs/fsck can update backfile of moutned loop device.

1. mkfs.f2fs image
2. mount -o loop image /mnt/f2fs/
3. mkfs.f2fs image -f

Before:
...
Info: format successful

After:
...
	Error: In use by loop device!

Signed-off-by: Chao Yu <chao@kernel.org>
---
 configure.ac             |  2 ++
 fsck/main.c              |  4 +--
 include/android_config.h |  2 ++
 lib/libf2fs.c            | 74 ++++++++++++++++++++++++++++++++++------
 mkfs/f2fs_format_main.c  |  7 ++--
 5 files changed, 74 insertions(+), 15 deletions(-)
diff mbox series

Patch

diff --git a/configure.ac b/configure.ac
index 123ddbb..21c6391 100644
--- a/configure.ac
+++ b/configure.ac
@@ -144,6 +144,8 @@  AC_CHECK_HEADERS(m4_flatten([
 	linux/fs.h
 	linux/hdreg.h
 	linux/limits.h
+	linux/loop.h
+	linux/major.h
 	linux/posix_acl.h
 	linux/types.h
 	linux/xattr.h
diff --git a/fsck/main.c b/fsck/main.c
index 1affa72..c4d0956 100644
--- a/fsck/main.c
+++ b/fsck/main.c
@@ -1111,8 +1111,8 @@  int main(int argc, char **argv)
 
 	f2fs_parse_options(argc, argv);
 
-	if (c.func != DUMP && f2fs_devs_are_umounted() < 0) {
-		if (errno == EBUSY) {
+	if (c.func != DUMP && (ret = f2fs_devs_are_umounted()) < 0) {
+		if (ret == -EBUSY) {
 			ret = -1;
 			if (c.func == FSCK)
 				ret = FSCK_OPERATIONAL_ERROR;
diff --git a/include/android_config.h b/include/android_config.h
index da8abcb..05b686e 100644
--- a/include/android_config.h
+++ b/include/android_config.h
@@ -6,6 +6,8 @@ 
 #define HAVE_FSYNC 1
 #define HAVE_LINUX_HDREG_H 1
 #define HAVE_LINUX_LIMITS_H 1
+#define HAVE_LINUX_LOOP_H 1
+#define HAVE_LINUX_MAJOR_H 1
 #define HAVE_POSIX_ACL_H 1
 #define HAVE_LINUX_TYPES_H 1
 #define HAVE_LINUX_XATTR_H 1
diff --git a/lib/libf2fs.c b/lib/libf2fs.c
index 2451201..8570689 100644
--- a/lib/libf2fs.c
+++ b/lib/libf2fs.c
@@ -19,6 +19,12 @@ 
 #endif
 #include <time.h>
 #include <sys/stat.h>
+#ifdef HAVE_LINUX_LOOP_H
+#include <linux/loop.h>
+#ifdef HAVE_LINUX_MAJOR_H
+#include <linux/major.h>
+#endif
+#endif
 #ifdef HAVE_SYS_IOCTL_H
 #include <sys/ioctl.h>
 #endif
@@ -756,7 +762,7 @@  int f2fs_dev_is_umounted(char *path)
 #ifdef _WIN32
 	return 0;
 #else
-	struct stat *st_buf;
+	struct stat st_buf;
 	int is_rootdev = 0;
 	int ret = 0;
 	char *rootdev_name = get_rootdev();
@@ -807,32 +813,78 @@  int f2fs_dev_is_umounted(char *path)
 	 * If f2fs is umounted with -l, the process can still use
 	 * the file system. In this case, we should not format.
 	 */
-	st_buf = malloc(sizeof(struct stat));
-	ASSERT(st_buf);
+	if (stat(path, &st_buf)) {
+		MSG(0, "Info: stat failed errno:%d\n", errno);
+		return -1;
+	}
 
-	if (stat(path, st_buf) == 0 && S_ISBLK(st_buf->st_mode)) {
+	if (S_ISBLK(st_buf.st_mode)) {
 		int fd = open(path, O_RDONLY | O_EXCL);
 
 		if (fd >= 0) {
 			close(fd);
 		} else if (errno == EBUSY) {
 			MSG(0, "\tError: In use by the system!\n");
-			free(st_buf);
-			return -1;
+			return -EBUSY;
 		}
+	} 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)
+		struct mntent *mnt;
+		struct stat st_loop;
+		FILE *f;
+
+		f = setmntent("/proc/mounts", "r");
+
+		while ((mnt = getmntent(f)) != NULL) {
+			struct loop_info64 loopinfo = {0, };
+			int loop_fd, err;
+
+			if (mnt->mnt_fsname[0] != '/')
+				continue;
+			if (stat(mnt->mnt_fsname, &st_loop) != 0)
+				continue;
+			if (!S_ISBLK(st_loop.st_mode))
+				continue;
+			if (major(st_loop.st_rdev) != LOOP_MAJOR)
+				continue;
+
+			loop_fd = open(mnt->mnt_fsname, O_RDONLY);
+			if (loop_fd < 0) {
+				MSG(0, "Info: open %s failed errno:%d\n",
+					mnt->mnt_fsname, 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);
+				return -1;
+			}
+
+			if (st_buf.st_dev == loopinfo.lo_device &&
+				st_buf.st_ino == loopinfo.lo_inode) {
+				MSG(0, "\tError: In use by loop device!\n");
+				return -EBUSY;
+			}
+		}
+#endif
 	}
-	free(st_buf);
 	return ret;
 #endif
 }
 
 int f2fs_devs_are_umounted(void)
 {
-	int i;
+	int ret, i;
 
-	for (i = 0; i < c.ndevs; i++)
-		if (f2fs_dev_is_umounted((char *)c.devices[i].path))
-			return -1;
+	for (i = 0; i < c.ndevs; i++) {
+		ret = f2fs_dev_is_umounted((char *)c.devices[i].path);
+		if (ret)
+			return ret;
+	}
 	return 0;
 }
 
diff --git a/mkfs/f2fs_format_main.c b/mkfs/f2fs_format_main.c
index 4de517a..f3316f7 100644
--- a/mkfs/f2fs_format_main.c
+++ b/mkfs/f2fs_format_main.c
@@ -443,6 +443,8 @@  static int f2fs_check_overwrite(void)
 
 int main(int argc, char *argv[])
 {
+	int ret;
+
 	f2fs_init_configuration();
 
 	f2fs_parse_options(argc, argv);
@@ -451,8 +453,9 @@  int main(int argc, char *argv[])
 
 	c.func = MKFS;
 
-	if (f2fs_devs_are_umounted() < 0) {
-		if (errno != EBUSY)
+	ret = f2fs_devs_are_umounted();
+	if (ret) {
+		if (ret != -EBUSY)
 			MSG(0, "\tError: Not available on mounted device!\n");
 		goto err_format;
 	}