diff mbox series

[V2] btrfs-prog: scrub: print message when scrubbing a read-only filesystem without r option

Message ID 1720292316-24008-1-git-send-email-zhanglikernel@gmail.com (mailing list archive)
State New, archived
Headers show
Series [V2] btrfs-prog: scrub: print message when scrubbing a read-only filesystem without r option | expand

Commit Message

Li Zhang July 6, 2024, 6:58 p.m. UTC
[enhancement]
When scrubbing a filesystem mounted read-only and without r
option, it aborts and there is no message associated with it.
So we need to print an error message when scrubbing a read-only
filesystem to tell the user what is going on here.

[implementation]
Move the error message from the main thread to each scrub thread,
previously the message was printed after all scrub threads
finished and without background mode.

[test]
Mount dev in read-only mode, then scrub it without r option

$ sudo mount /dev/vdb -o ro /mnt/
$ sudo btrfs scrub start /mnt/
ERROR: this filesystem is mounted readonly, but scrub option without r option.

issue: #666

V1:
  Output directly within the thread.

V2:
  Use the getmntent() function to obtain a bitmask to check
  whether the file system is mounted read-only.

Signed-off-by: Li Zhang <zhanglikernel@gmail.com>
---
 cmds/scrub.c | 35 +++++++++++++++++++++++++++++++++++
 1 file changed, 35 insertions(+)
diff mbox series

Patch

diff --git a/cmds/scrub.c b/cmds/scrub.c
index 202690d..79011a2 100644
--- a/cmds/scrub.c
+++ b/cmds/scrub.c
@@ -42,6 +42,7 @@ 
 #include <syscall.h>
 #include <time.h>
 #include <uuid/uuid.h>
+#include <mntent.h>
 #include "kernel-lib/sizes.h"
 #include "kernel-shared/volumes.h"
 #include "common/defs.h"
@@ -1224,6 +1225,34 @@  static u64 write_scrub_device_limit(int fd, u64 devid, u64 limit)
 	return ret;
 }
 
+/*
+ * Check if given path is a mount read only.
+ *
+ * Return: 1 if yes,
+ *         0 if no,
+ *        -1 for error
+ */
+static int path_is_mount_readonly(const char *path){
+	FILE *f;
+	struct mntent *mnt;
+	int ret = -1;
+	
+	f = setmntent("/proc/self/mounts", "r");
+	if (f == NULL)
+		return -1;
+	while ((mnt = getmntent(f)) != NULL) {
+		if (strcmp(mnt->mnt_dir, path))
+			continue;
+		if (hasmntopt(mnt, MNTOPT_RO))
+			ret = 1;
+		else
+			ret = 0;
+		break;
+	}
+	endmntent(f);
+	return ret;
+}
+
 static int scrub_start(const struct cmd_struct *cmd, int argc, char **argv,
 		       bool resume)
 {
@@ -1320,11 +1349,17 @@  static int scrub_start(const struct cmd_struct *cmd, int argc, char **argv,
 	}
 
 	path = argv[optind];
+	if (strlen(path) > 1 && '/' == path[strlen(path)-1])
+		path[strlen(path)-1] = 0;
 
 	fdmnt = btrfs_open_mnt(path);
 	if (fdmnt < 0)
 		return 1;
 
+	if (path_is_mount_readonly(path) && !readonly){
+		error("The file system is mounted read-only, but the scrub options do not have an r option.");
+		return 1;
+	}
 	ret = get_fs_info(path, &fi_args, &di_args);
 	if (ret) {
 		errno = -ret;