diff --git a/cmds-filesystem.c b/cmds-filesystem.c index 696c104e2b..9f7bb343ff 100644 --- a/cmds-filesystem.c +++ b/cmds-filesystem.c @@ -26,6 +26,7 @@ #include #include #include +#include #include #include @@ -39,12 +40,14 @@ #include "list_sort.h" #include "disk-io.h" #include "help.h" +#include "fsfeatures.h" /* * for btrfs fi show, we maintain a hash of fsids we've already printed. * This way we don't print dups if a given FS is mounted more than once. */ static struct seen_fsid *seen_fsid_hash[SEEN_FSID_HASH_SIZE] = {NULL,}; +static mode_t defrag_open_mode = O_RDONLY; static const char * const filesystem_cmd_group_usage[] = { "btrfs filesystem [] []", @@ -880,7 +883,7 @@ static int defrag_callback(const char *fpath, const struct stat *sb, if ((typeflag == FTW_F) && S_ISREG(sb->st_mode)) { if (defrag_global_verbose) printf("%s\n", fpath); - fd = open(fpath, O_RDWR); + fd = open(fpath, defrag_open_mode); if (fd < 0) { goto error; } @@ -917,6 +920,13 @@ static int cmd_filesystem_defrag(int argc, char **argv) int compress_type = BTRFS_COMPRESS_NONE; DIR *dirstream; + /* + * Kernel 4.19+ supports defragmention of files open read-only, + * otherwise it's an ETXTBSY error + */ + if (get_running_kernel_version() < KERNEL_VERSION(4,19,0)) + defrag_open_mode = O_RDWR; + /* * Kernel has a different default (256K) that is supposed to be safe, * but it does not defragment very well. The 32M will likely lead to @@ -1017,7 +1027,7 @@ static int cmd_filesystem_defrag(int argc, char **argv) int defrag_err = 0; dirstream = NULL; - fd = open_file_or_dir(argv[i], &dirstream); + fd = open_file_or_dir3(argv[i], &dirstream, defrag_open_mode); if (fd < 0) { error("cannot open %s: %m", argv[i]); ret = -errno;