btrfs-progs: mkfs: Separate shrink from rootdir

Make --shrink a separate option for --rootdir, and change the default to
off.

The shrinking behaviour is not a commonly used feature but can be useful
for creating minimal pre-filled images, in one step, without requiring
to mount.

Signed-off-by: Qu Wenruo <wqu@suse.com>
[ update changelog and error messages ]
Signed-off-by: David Sterba <dsterba@suse.com>
master
Qu Wenruo 2017-10-19 17:13:55 +08:00 committed by David Sterba
parent c28418daed
commit 1c9c5f7fb3
4 changed files with 54 additions and 8 deletions

View File

@ -101,6 +101,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

View File

@ -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,9 @@ int main(int argc, char **argv)
case 'q':
verbose = 0;
break;
case GETOPT_VAL_SHRINK:
shrink_rootdir = true;
break;
case GETOPT_VAL_HELP:
default:
print_usage(c != GETOPT_VAL_HELP);
@ -861,6 +868,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 must be used with --rootdir");
goto error;
}
if (*fs_uuid) {
uuid_t dummy_uuid;
@ -1189,10 +1200,14 @@ 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;
}
}
}

View File

@ -899,11 +899,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;
@ -931,5 +933,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;
}

View File

@ -32,6 +32,7 @@ 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