Make --shrink a separate option for --rootdir, and make it default to off. So this will cause less confusion.
Signed-off-by: Qu Wenruo <w...@suse.com> --- Documentation/mkfs.btrfs.asciidoc | 11 +++++++++++ mkfs/main.c | 27 +++++++++++++++++++++------ mkfs/rootdir.c | 21 ++++++++++++++++++++- mkfs/rootdir.h | 3 ++- 4 files changed, 54 insertions(+), 8 deletions(-) diff --git a/Documentation/mkfs.btrfs.asciidoc b/Documentation/mkfs.btrfs.asciidoc index d53d9e265fb7..5ddbedbcea97 100644 --- a/Documentation/mkfs.btrfs.asciidoc +++ b/Documentation/mkfs.btrfs.asciidoc @@ -106,6 +106,17 @@ Please see the mount option 'discard' for that in `btrfs`(5). *-r|--rootdir <rootdir>*:: Populate the toplevel subvolume with files from 'rootdir'. This does not require root permissions and does not mount the filesystem. ++ +NOTE: This option may enlarge the image or file to ensure it's large enough to +contain the files from 'rootdir'. + +*--shrink*: +Shrink the filesystem to its minimal size, only works with *-r|--rootdir* +option. ++ +NOTE: If the destination is regular file, this option will also reduce the +file size. Or it will only reduce the filesystem available space. +Extra space will not be usable unless resized using 'btrfs filesystem resize'. *-O|--features <feature1>[,<feature2>...]*:: A list of filesystem features turned on at mkfs time. Not all features are diff --git a/mkfs/main.c b/mkfs/main.c index 6aefb50a8033..1d72702414bc 100644 --- a/mkfs/main.c +++ b/mkfs/main.c @@ -731,9 +731,11 @@ int main(int argc, char **argv) int ssd = 0; int force_overwrite = 0; char *source_dir = NULL; - int source_dir_set = 0; + bool source_dir_set = false; + bool shrink_rootdir = false; u64 source_dir_size = 0; u64 min_dev_size; + u64 shrink_size; int dev_cnt = 0; int saved_optind; char fs_uuid[BTRFS_UUID_UNPARSED_SIZE] = { 0 }; @@ -743,6 +745,7 @@ int main(int argc, char **argv) while(1) { int c; + enum { GETOPT_VAL_SHRINK = 257 }; static const struct option long_options[] = { { "alloc-start", required_argument, NULL, 'A'}, { "byte-count", required_argument, NULL, 'b' }, @@ -760,6 +763,7 @@ int main(int argc, char **argv) { "features", required_argument, NULL, 'O' }, { "uuid", required_argument, NULL, 'U' }, { "quiet", 0, NULL, 'q' }, + { "shrink", no_argument, NULL, GETOPT_VAL_SHRINK }, { "help", no_argument, NULL, GETOPT_VAL_HELP }, { NULL, 0, NULL, 0} }; @@ -827,7 +831,7 @@ int main(int argc, char **argv) goto success; case 'r': source_dir = optarg; - source_dir_set = 1; + source_dir_set = true; break; case 'U': strncpy(fs_uuid, optarg, @@ -839,6 +843,10 @@ int main(int argc, char **argv) case 'q': verbose = 0; break; + case GETOPT_VAL_SHRINK: + shrink_rootdir = true; + break; + break; case GETOPT_VAL_HELP: default: print_usage(c != GETOPT_VAL_HELP); @@ -861,6 +869,10 @@ int main(int argc, char **argv) error("the option -r is limited to a single device"); goto error; } + if (shrink_rootdir && !source_dir_set) { + error("the option --shrink can only be paired with -r"); + goto error; + } if (*fs_uuid) { uuid_t dummy_uuid; @@ -1186,10 +1198,13 @@ raid_groups: error("error wihle filling filesystem: %d", ret); goto out; } - ret = btrfs_mkfs_shrink_fs(fs_info, NULL); - if (ret < 0) { - error("error while shrinking filesystem: %d", ret); - goto out; + if (shrink_rootdir) { + ret = btrfs_mkfs_shrink_fs(fs_info, &shrink_size, + shrink_rootdir); + if (ret < 0) { + error("error while shrinking filesystem: %d", ret); + goto out; + } } } diff --git a/mkfs/rootdir.c b/mkfs/rootdir.c index 9593bbc25b39..aa42d186a43f 100644 --- a/mkfs/rootdir.c +++ b/mkfs/rootdir.c @@ -898,11 +898,13 @@ err: return ret; } -int btrfs_mkfs_shrink_fs(struct btrfs_fs_info *fs_info, u64 *new_size_ret) +int btrfs_mkfs_shrink_fs(struct btrfs_fs_info *fs_info, u64 *new_size_ret, + bool shrink_file_size) { u64 new_size; struct btrfs_device *device; struct list_head *cur; + struct stat64 file_stat; int nr_devs = 0; int ret; @@ -930,5 +932,22 @@ int btrfs_mkfs_shrink_fs(struct btrfs_fs_info *fs_info, u64 *new_size_ret) return ret; if (new_size_ret) *new_size_ret = new_size; + + if (shrink_file_size) { + ret = fstat64(device->fd, &file_stat); + if (ret < 0) { + error("failed to stat devid %llu: %s", device->devid, + strerror(errno)); + return ret; + } + if (!S_ISREG(file_stat.st_mode)) + return ret; + ret = ftruncate64(device->fd, new_size); + if (ret < 0) { + error("failed to truncate device file of devid %llu: %s", + device->devid, strerror(errno)); + return ret; + } + } return ret; } diff --git a/mkfs/rootdir.h b/mkfs/rootdir.h index e5b739ede48a..78bc9c90f7c5 100644 --- a/mkfs/rootdir.h +++ b/mkfs/rootdir.h @@ -29,5 +29,6 @@ int btrfs_mkfs_fill_dir(const char *source_dir, struct btrfs_root *root, bool verbose); u64 btrfs_mkfs_size_dir(const char *dir_name, u32 sectorsize, u64 min_dev_size, u64 meta_profile, u64 data_profile); -int btrfs_mkfs_shrink_fs(struct btrfs_fs_info *fs_info, u64 *new_size_ret); +int btrfs_mkfs_shrink_fs(struct btrfs_fs_info *fs_info, u64 *new_size_ret, + bool shrink_file_size); #endif -- 2.14.2 -- To unsubscribe from this list: send the line "unsubscribe linux-btrfs" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html