summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDavid Sterba <dsterba@suse.cz>2017-08-31 18:34:37 +0200
committerDavid Sterba <dsterba@suse.com>2017-09-08 16:15:05 +0200
commit162fdf95383bd6685cce17f9c52cc858fef2c09c (patch)
tree8c767bcce1ce252a6740438a3c3bb0c3dd4f9768
parent8609c8bad68528f668d9ce564b868aa4828107a0 (diff)
btrfs-progs: check: add option to skip mount checks
Sometimes it's needed to do a check on a mounted filesystem. This should work fine on a quiescent filesystem or a read-only mount. Changes on the block device done by kernel might confuse the userspace checker and it might crash when it reads some stale data. Repair without mount checks is not supported right now. Signed-off-by: David Sterba <dsterba@suse.cz>
-rw-r--r--Documentation/btrfs-check.asciidoc12
-rw-r--r--cmds-check.c50
2 files changed, 49 insertions, 13 deletions
diff --git a/Documentation/btrfs-check.asciidoc b/Documentation/btrfs-check.asciidoc
index fa054e45..fbf48847 100644
--- a/Documentation/btrfs-check.asciidoc
+++ b/Documentation/btrfs-check.asciidoc
@@ -3,7 +3,7 @@ btrfs-check(8)
NAME
----
-btrfs-check - check or repair an unmounted btrfs filesystem
+btrfs-check - check or repair a btrfs filesystem
SYNOPSIS
--------
@@ -13,7 +13,9 @@ DESCRIPTION
-----------
The filesystem checker is used to verify structural integrity of a filesystem
-and attempt to repair it if requested. The filesystem must be unmounted.
+and attempt to repair it if requested. It is recommended to unmount the
+filesystem prior to running the check, but it is possible to start checking a
+mounted filesystem (see '--force').
By default, *btrfs check* will not modify the device but you can reaffirm that
by the option '--readonly'.
@@ -120,6 +122,12 @@ needs to re-read blocks when needed. This may increase run time.
NOTE: 'lowmem' mode does not work with '--repair' yet, and is still considered
experimental.
+--force::
+allow to work on a mounted filesystem. Note that this should work fine on a
+quiescent or read-only mounted filesystem but may crash if the device is
+changed externally, eg. by the kernel module. Repair without mount checks is
+not supported right now.
+
EXIT STATUS
-----------
*btrfs check* returns a zero exit status if it succeeds. Non zero is
diff --git a/cmds-check.c b/cmds-check.c
index a633d044..006edbde 100644
--- a/cmds-check.c
+++ b/cmds-check.c
@@ -12730,6 +12730,7 @@ const char * const cmd_check_usage[] = {
"",
"-s|--super <superblock> use this superblock copy",
"-b|--backup use the first valid backup root copy",
+ "--force skip mount checks, repair is not possible",
"--repair try to repair the filesystem",
"--readonly run in read-only mode (default)",
"--init-csum-tree create a new CRC tree",
@@ -12761,7 +12762,7 @@ int cmd_check(int argc, char **argv)
u64 tree_root_bytenr = 0;
u64 chunk_root_bytenr = 0;
char uuidbuf[BTRFS_UUID_UNPARSED_SIZE];
- int ret;
+ int ret = 0;
int err = 0;
u64 num;
int init_csum_tree = 0;
@@ -12770,13 +12771,15 @@ int cmd_check(int argc, char **argv)
int qgroup_report = 0;
int qgroups_repaired = 0;
unsigned ctree_flags = OPEN_CTREE_EXCLUSIVE;
+ int force = 0;
while(1) {
int c;
enum { GETOPT_VAL_REPAIR = 257, GETOPT_VAL_INIT_CSUM,
GETOPT_VAL_INIT_EXTENT, GETOPT_VAL_CHECK_CSUM,
GETOPT_VAL_READONLY, GETOPT_VAL_CHUNK_TREE,
- GETOPT_VAL_MODE, GETOPT_VAL_CLEAR_SPACE_CACHE };
+ GETOPT_VAL_MODE, GETOPT_VAL_CLEAR_SPACE_CACHE,
+ GETOPT_VAL_FORCE };
static const struct option long_options[] = {
{ "super", required_argument, NULL, 's' },
{ "repair", no_argument, NULL, GETOPT_VAL_REPAIR },
@@ -12798,6 +12801,7 @@ int cmd_check(int argc, char **argv)
GETOPT_VAL_MODE },
{ "clear-space-cache", required_argument, NULL,
GETOPT_VAL_CLEAR_SPACE_CACHE},
+ { "force", no_argument, NULL, GETOPT_VAL_FORCE },
{ NULL, 0, NULL, 0}
};
@@ -12882,6 +12886,9 @@ int cmd_check(int argc, char **argv)
}
ctree_flags |= OPEN_CTREE_WRITES;
break;
+ case GETOPT_VAL_FORCE:
+ force = 1;
+ break;
}
}
@@ -12910,15 +12917,36 @@ int cmd_check(int argc, char **argv)
radix_tree_init();
cache_tree_init(&root_cache);
- if((ret = check_mounted(argv[optind])) < 0) {
- error("could not check mount status: %s", strerror(-ret));
- err |= !!ret;
- goto err_out;
- } else if(ret) {
- error("%s is currently mounted, aborting", argv[optind]);
- ret = -EBUSY;
- err |= !!ret;
- goto err_out;
+ ret = check_mounted(argv[optind]);
+ if (!force) {
+ if (ret < 0) {
+ error("could not check mount status: %s",
+ strerror(-ret));
+ err |= !!ret;
+ goto err_out;
+ } else if (ret) {
+ error(
+"%s is currently mounted, use --force if you really intend to check the filesystem",
+ argv[optind]);
+ ret = -EBUSY;
+ err |= !!ret;
+ goto err_out;
+ }
+ } else {
+ if (repair) {
+ error("repair and --force is not yet supported");
+ ret = 1;
+ err |= !!ret;
+ goto err_out;
+ }
+ if (ret < 0) {
+ warning(
+"cannot check mount status of %s, the filesystem could be mounted, continuing because of --force",
+ argv[optind]);
+ } else if (ret) {
+ warning(
+ "filesystem mounted, continuing because of --force");
+ }
}
/* only allow partial opening under repair mode */