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

View File

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