Skip to content

[PATCH v3] btrfs-progs: add slack space for mkfs --shrink #981

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 1 commit into
base: devel
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
26 changes: 25 additions & 1 deletion mkfs/main.c
Original file line number Diff line number Diff line change
Expand Up @@ -464,6 +464,8 @@ 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"),
"",
Expand Down Expand Up @@ -1176,6 +1178,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;
Expand Down Expand Up @@ -1220,6 +1223,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,
Expand Down Expand Up @@ -1250,6 +1254,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
Expand Down Expand Up @@ -1386,6 +1392,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;
Expand Down Expand Up @@ -1433,6 +1442,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;
Expand Down Expand Up @@ -2104,8 +2119,17 @@ int BOX_MAIN(mkfs)(int argc, char **argv)

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");
Expand Down
23 changes: 22 additions & 1 deletion mkfs/rootdir.c
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,8 @@
*/

#include "kerncompat.h"
#include <linux/fs.h>
#include <sys/ioctl.h>
#include <sys/stat.h>
#include <sys/xattr.h>
#include <dirent.h>
Expand Down Expand Up @@ -52,6 +54,7 @@
#include "common/root-tree-utils.h"
#include "common/path-utils.h"
#include "common/rbtree-utils.h"
#include "common/units.h"
#include "mkfs/rootdir.h"

#define LZO_LEN 4
Expand Down Expand Up @@ -1925,9 +1928,10 @@ static int set_device_size(struct btrfs_fs_info *fs_info,
}

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;
u64 blk_device_size;
struct btrfs_device *device;
struct list_head *cur;
struct stat file_stat;
Expand Down Expand Up @@ -1955,6 +1959,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);
Expand All @@ -1969,6 +1981,15 @@ int btrfs_mkfs_shrink_fs(struct btrfs_fs_info *fs_info, u64 *new_size_ret,
error("failed to stat devid %llu: %m", device->devid);
return ret;
}
if (S_ISBLK(file_stat.st_mode)) {
ioctl(device->fd, BLKGETSIZE64, &blk_device_size);
if (blk_device_size < new_size) {
warning("blkdev size %llu (%s) is smaller than fs size %llu (%s)",
blk_device_size,
pretty_size(blk_device_size), new_size,
pretty_size(new_size));
}
}
if (!S_ISREG(file_stat.st_mode))
return ret;
ret = ftruncate(device->fd, new_size);
Expand Down
2 changes: 1 addition & 1 deletion mkfs/rootdir.h
Original file line number Diff line number Diff line change
Expand Up @@ -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