btrfs-progs: mkfs: add ro flag to --subvol

Adds a flag to mkfs.btrfs --subvol to allow subvolumes to be created
readonly.

Signed-off-by: Mark Harmstone <maharmstone@fb.com>
This commit is contained in:
Mark Harmstone 2024-08-27 11:49:45 +01:00 committed by David Sterba
parent fa70df7e78
commit ec8a6b1536
7 changed files with 21 additions and 6 deletions

View File

@ -163,6 +163,7 @@ OPTIONS
*flags* is an optional comma-separated list of modifiers. Valid choices are: *flags* is an optional comma-separated list of modifiers. Valid choices are:
* *default*: create as default subvolume (this can only be specified once) * *default*: create as default subvolume (this can only be specified once)
* *ro*: create as readonly subvolume
--shrink --shrink
Shrink the filesystem to its minimal size, only works with *--rootdir* option. Shrink the filesystem to its minimal size, only works with *--rootdir* option.

View File

@ -66,7 +66,8 @@ error:
* The created tree root would have its root_ref as 1. * The created tree root would have its root_ref as 1.
* Thus for subvolumes caller needs to properly add ROOT_BACKREF items. * Thus for subvolumes caller needs to properly add ROOT_BACKREF items.
*/ */
int btrfs_make_subvolume(struct btrfs_trans_handle *trans, u64 objectid) int btrfs_make_subvolume(struct btrfs_trans_handle *trans, u64 objectid,
bool readonly)
{ {
struct btrfs_fs_info *fs_info = trans->fs_info; struct btrfs_fs_info *fs_info = trans->fs_info;
struct btrfs_root *root; struct btrfs_root *root;
@ -98,6 +99,13 @@ int btrfs_make_subvolume(struct btrfs_trans_handle *trans, u64 objectid)
ret = btrfs_make_root_dir(trans, root, BTRFS_FIRST_FREE_OBJECTID); ret = btrfs_make_root_dir(trans, root, BTRFS_FIRST_FREE_OBJECTID);
if (ret < 0) if (ret < 0)
goto error; goto error;
btrfs_set_stack_inode_flags(&root->root_item.inode,
BTRFS_INODE_ROOT_ITEM_INIT);
if (readonly)
btrfs_set_root_flags(&root->root_item, BTRFS_ROOT_SUBVOL_RDONLY);
ret = btrfs_update_root(trans, fs_info->tree_root, &root->root_key, ret = btrfs_update_root(trans, fs_info->tree_root, &root->root_key,
&root->root_item); &root->root_item);
if (ret < 0) if (ret < 0)

View File

@ -21,7 +21,8 @@
int btrfs_make_root_dir(struct btrfs_trans_handle *trans, int btrfs_make_root_dir(struct btrfs_trans_handle *trans,
struct btrfs_root *root, u64 objectid); struct btrfs_root *root, u64 objectid);
int btrfs_make_subvolume(struct btrfs_trans_handle *trans, u64 objectid); int btrfs_make_subvolume(struct btrfs_trans_handle *trans, u64 objectid,
bool readonly);
int btrfs_link_subvolume(struct btrfs_trans_handle *trans, int btrfs_link_subvolume(struct btrfs_trans_handle *trans,
struct btrfs_root *parent_root, struct btrfs_root *parent_root,
u64 parent_dir, const char *name, u64 parent_dir, const char *name,

View File

@ -1022,13 +1022,14 @@ static int init_btrfs(struct btrfs_mkfs_config *cfg, struct btrfs_root *root,
BTRFS_FIRST_FREE_OBJECTID); BTRFS_FIRST_FREE_OBJECTID);
/* subvol for fs image file */ /* subvol for fs image file */
ret = btrfs_make_subvolume(trans, CONV_IMAGE_SUBVOL_OBJECTID); ret = btrfs_make_subvolume(trans, CONV_IMAGE_SUBVOL_OBJECTID, false);
if (ret < 0) { if (ret < 0) {
error("failed to create subvolume image root: %d", ret); error("failed to create subvolume image root: %d", ret);
goto err; goto err;
} }
/* subvol for data relocation tree */ /* subvol for data relocation tree */
ret = btrfs_make_subvolume(trans, BTRFS_DATA_RELOC_TREE_OBJECTID); ret = btrfs_make_subvolume(trans, BTRFS_DATA_RELOC_TREE_OBJECTID,
false);
if (ret < 0) { if (ret < 0) {
error("failed to create DATA_RELOC root: %d", ret); error("failed to create DATA_RELOC root: %d", ret);
goto err; goto err;

View File

@ -1036,6 +1036,8 @@ static int parse_subvol_flags(struct rootdir_subvol *subvol, const char *flags)
if (!strcmp(buf, "default")) { if (!strcmp(buf, "default")) {
subvol->is_default = true; subvol->is_default = true;
} else if (!strcmp(buf, "ro")) {
subvol->readonly = true;
} else if (buf[0] != 0) { } else if (buf[0] != 0) {
error("unrecognized subvol flag \"%s\"", buf); error("unrecognized subvol flag \"%s\"", buf);
ret = 1; ret = 1;
@ -1988,7 +1990,8 @@ raid_groups:
goto out; goto out;
} }
ret = btrfs_make_subvolume(trans, BTRFS_DATA_RELOC_TREE_OBJECTID); ret = btrfs_make_subvolume(trans, BTRFS_DATA_RELOC_TREE_OBJECTID,
false);
if (ret) { if (ret) {
error("unable to create data reloc tree: %d", ret); error("unable to create data reloc tree: %d", ret);
goto out; goto out;

View File

@ -430,7 +430,7 @@ static int ftw_add_subvol(const char *full_path, const struct stat *st,
subvol_id = next_subvol_id++; subvol_id = next_subvol_id++;
ret = btrfs_make_subvolume(g_trans, subvol_id); ret = btrfs_make_subvolume(g_trans, subvol_id, subvol->readonly);
if (ret < 0) { if (ret < 0) {
errno = -ret; errno = -ret;
error("failed to create subvolume: %m"); error("failed to create subvolume: %m");

View File

@ -33,6 +33,7 @@ struct rootdir_subvol {
char *dir; char *dir;
char *full_path; char *full_path;
bool is_default; bool is_default;
bool readonly;
}; };
int btrfs_mkfs_fill_dir(struct btrfs_trans_handle *trans, const char *source_dir, int btrfs_mkfs_fill_dir(struct btrfs_trans_handle *trans, const char *source_dir,