@@ -461,6 +461,7 @@ static const char * const mkfs_usage[] = {
OPTLINE("", "- default - the SUBDIR will be a subvolume and also set as default (can be specified only once)"),
OPTLINE("", "- default-ro - like 'default' and is created as read-only subvolume (can be specified only once)"),
OPTLINE("--shrink", "(with --rootdir) shrink the filled filesystem to minimal size"),
+ OPTLINE("--shrink-slack-size SIZE", "(with --shrink) include extra slack space after shrinking (default 0)"),
OPTLINE("-K|--nodiscard", "do not perform whole device TRIM"),
OPTLINE("-f|--force", "force overwrite of existing filesystem"),
"",
@@ -1173,6 +1174,7 @@ int BOX_MAIN(mkfs)(int argc, char **argv)
int i;
bool ssd = false;
bool shrink_rootdir = false;
+ u64 shrink_slack_size = 0;
u64 source_dir_size = 0;
u64 min_dev_size;
u64 shrink_size;
@@ -1217,6 +1219,7 @@ int BOX_MAIN(mkfs)(int argc, char **argv)
int c;
enum {
GETOPT_VAL_SHRINK = GETOPT_VAL_FIRST,
+ GETOPT_VAL_SHRINK_SLACK_SIZE,
GETOPT_VAL_CHECKSUM,
GETOPT_VAL_GLOBAL_ROOTS,
GETOPT_VAL_DEVICE_UUID,
@@ -1247,6 +1250,8 @@ int BOX_MAIN(mkfs)(int argc, char **argv)
{ "quiet", 0, NULL, 'q' },
{ "verbose", 0, NULL, 'v' },
{ "shrink", no_argument, NULL, GETOPT_VAL_SHRINK },
+ { "shrink-slack-size", required_argument, NULL,
+ GETOPT_VAL_SHRINK_SLACK_SIZE },
{ "compress", required_argument, NULL,
GETOPT_VAL_COMPRESS },
#if EXPERIMENTAL
@@ -1383,6 +1388,9 @@ int BOX_MAIN(mkfs)(int argc, char **argv)
case GETOPT_VAL_SHRINK:
shrink_rootdir = true;
break;
+ case GETOPT_VAL_SHRINK_SLACK_SIZE:
+ shrink_slack_size = arg_strtou64_with_suffix(optarg);
+ break;
case GETOPT_VAL_CHECKSUM:
csum_type = parse_csum_type(optarg);
break;
@@ -1430,6 +1438,12 @@ int BOX_MAIN(mkfs)(int argc, char **argv)
ret = 1;
goto error;
}
+ if (shrink_slack_size > 0 && !shrink_rootdir) {
+ error("the option --shrink-slack-size must be used with --shrink");
+ ret = 1;
+ goto error;
+
+ }
if (!list_empty(&subvols) && source_dir == NULL) {
error("option --subvol must be used with --rootdir");
ret = 1;
@@ -2108,8 +2122,17 @@ raid_groups:
if (shrink_rootdir) {
pr_verbose(LOG_DEFAULT, " Shrink: yes\n");
+ if (shrink_slack_size > 0) {
+ pr_verbose(
+ LOG_DEFAULT,
+ " Shrink slack: %llu (%s)\n",
+ shrink_slack_size,
+ pretty_size(shrink_slack_size));
+ }
ret = btrfs_mkfs_shrink_fs(fs_info, &shrink_size,
- shrink_rootdir);
+ shrink_rootdir,
+ shrink_slack_size);
+
if (ret < 0) {
errno = -ret;
error("error while shrinking filesystem: %m");
@@ -48,6 +48,7 @@
#include "common/internal.h"
#include "common/messages.h"
#include "common/utils.h"
+#include "common/units.h"
#include "common/extent-tree-utils.h"
#include "common/root-tree-utils.h"
#include "common/path-utils.h"
@@ -1924,7 +1925,7 @@ err:
}
int btrfs_mkfs_shrink_fs(struct btrfs_fs_info *fs_info, u64 *new_size_ret,
- bool shrink_file_size)
+ bool shrink_file_size, u64 slack_size)
{
u64 new_size;
struct btrfs_device *device;
@@ -1954,6 +1955,14 @@ int btrfs_mkfs_shrink_fs(struct btrfs_fs_info *fs_info, u64 *new_size_ret,
return -EUCLEAN;
}
+ if (!IS_ALIGNED(slack_size, fs_info->sectorsize)) {
+ error("slack size %llu not aligned to %u",
+ slack_size, fs_info->sectorsize);
+ return -EUCLEAN;
+ }
+
+ new_size += slack_size;
+
device = list_entry(fs_info->fs_devices->devices.next,
struct btrfs_device, dev_list);
ret = set_device_size(fs_info, device, new_size);
@@ -52,6 +52,6 @@ int btrfs_mkfs_fill_dir(struct btrfs_trans_handle *trans, const char *source_dir
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,
- bool shrink_file_size);
+ bool shrink_file_size, u64 slack_size);
#endif
This patch adds a flag `--shrink-slack-size SIZE` to the mkfs.btrfs allowing users to specify slack when shrinking the filesystem. Previously if you wanted to use --shrink and include extra space in the filesystem you would need to use btrfs resize, however, this requires mounting the filesystem which requires CAP_SYS_ADMIN. The new syntax is: `mkfs.btrfs --shrink --shrink-slack-size SIZE` Where slack size is an argument specifying the desired free space to add to a shrunk fs. If not provided, the default slack size is 0. I have not added any upper bounds checking on SIZE as I'm not sure it's necessary. The following command will succeed without warning even if `$DEVICE` is a block device smaller than 10T. However, mounting `$DEVICE` will fail. `mkfs.btrfs -f $DEVICE --root $ROOT --shrink --shrink-slack-size 10T` I don't know if this would be considered incorrect because $DEVICE could also be a regular file that can ftruncate up to the appropriate size. Should I add a warning message, or leave it to mount time to indicate that something is wrong? V2: - change --shrink[=SLACK SIZE] to --shrink-slack-size SIZE - check for slack size alignment - fix formatting - remove new_size > device size warning message Signed-off-by: Leo Martins <loemra.dev@gmail.com> --- mkfs/main.c | 25 ++++++++++++++++++++++++- mkfs/rootdir.c | 11 ++++++++++- mkfs/rootdir.h | 2 +- 3 files changed, 35 insertions(+), 3 deletions(-)