btrfs-progs: mkfs: avoid dynamic allocation when doing --subvol

Reworks mkfs.btrfs --subvol so that dir and full_path in struct
rootdir_subvol are stored as arrays rather than pointers.

Signed-off-by: Mark Harmstone <maharmstone@fb.com>
This commit is contained in:
Mark Harmstone 2024-09-30 15:56:07 +01:00 committed by Qu Wenruo
parent 59f74c25af
commit 6a1d4adad1
3 changed files with 16 additions and 40 deletions

View File

@ -1056,7 +1056,6 @@ int BOX_MAIN(mkfs)(int argc, char **argv)
char *label = NULL;
int nr_global_roots = sysconf(_SC_NPROCESSORS_ONLN);
char *source_dir = NULL;
size_t source_dir_len = 0;
struct rootdir_subvol *rds;
bool has_default_subvol = false;
LIST_HEAD(subvols);
@ -1245,10 +1244,12 @@ int BOX_MAIN(mkfs)(int argc, char **argv)
}
}
if (valid_prefix)
subvol->dir = strndup(colon + 1, strlen(colon + 1));
else
subvol->dir = strdup(optarg);
if (arg_copy_path(subvol->dir, valid_prefix ? colon + 1 : optarg,
sizeof(subvol->dir))) {
error("--subvol path too long");
ret = 1;
goto error;
}
if (subvol->is_default) {
if (has_default_subvol) {
@ -1343,57 +1344,37 @@ int BOX_MAIN(mkfs)(int argc, char **argv)
free(source_dir);
source_dir = canonical;
source_dir_len = strlen(source_dir);
}
list_for_each_entry(rds, &subvols, list) {
char *path, *canonical;
char path[PATH_MAX];
struct rootdir_subvol *rds2;
size_t dir_len;
dir_len = strlen(rds->dir);
path = malloc(source_dir_len + 1 + dir_len + 1);
if (!path) {
error_msg(ERROR_MSG_MEMORY, NULL);
if (path_cat_out(path, source_dir, rds->dir)) {
error("path invalid");
ret = 1;
goto error;
}
memcpy(path, source_dir, source_dir_len);
path[source_dir_len] = '/';
memcpy(path + source_dir_len + 1, rds->dir, dir_len + 1);
canonical = realpath(path, NULL);
if (!canonical) {
if (!realpath(path, rds->full_path)) {
error("could not get canonical path to %s", rds->dir);
free(path);
ret = 1;
goto error;
}
free(path);
path = canonical;
if (!path_exists(path)) {
if (!path_exists(rds->full_path)) {
error("subvolume %s does not exist", rds->dir);
free(path);
ret = 1;
goto error;
}
if (!path_is_dir(path)) {
if (!path_is_dir(rds->full_path)) {
error("subvolume %s is not a directory", rds->dir);
free(path);
ret = 1;
goto error;
}
rds->full_path = path;
if (strlen(path) < source_dir_len + 1 ||
memcmp(path, source_dir, source_dir_len) != 0 ||
path[source_dir_len] != '/') {
if (!path_is_in_dir(source_dir, rds->full_path)) {
error("subvolume %s is not a child of %s", rds->dir, source_dir);
ret = 1;
goto error;
@ -1402,7 +1383,7 @@ int BOX_MAIN(mkfs)(int argc, char **argv)
for (rds2 = list_first_entry(&subvols, struct rootdir_subvol, list);
rds2 != rds;
rds2 = list_next_entry(rds2, list)) {
if (strcmp(rds2->full_path, path) == 0) {
if (strcmp(rds2->full_path, rds->full_path) == 0) {
error("subvolume %s specified more than once", rds->dir);
ret = 1;
goto error;
@ -2113,8 +2094,6 @@ error:
struct rootdir_subvol *head;
head = list_entry(subvols.next, struct rootdir_subvol, list);
free(head->dir);
free(head->full_path);
list_del(&head->list);
free(head);
}

View File

@ -711,9 +711,6 @@ static int ftw_add_inode(const char *full_path, const struct stat *st,
ret = ftw_add_subvol(full_path, st, typeflag,
ftwbuf, rds);
free(rds->dir);
free(rds->full_path);
list_del(&rds->list);
free(rds);

View File

@ -30,8 +30,8 @@ struct btrfs_root;
struct rootdir_subvol {
struct list_head list;
char *dir;
char *full_path;
char dir[PATH_MAX];
char full_path[PATH_MAX];
bool is_default;
bool readonly;
};