Skip to content

Commit

Permalink
btrfs-progs: subvolume delete: add new option for recursive deletion
Browse files Browse the repository at this point in the history
Add new option --recursive 'btrfs subvol delete', causing it to pass the
BTRFS_UTIL_DELETE_SUBVOLUME_RECURSIVE flag through to libbtrfsutil.

This can work in two modes, depending on the user:

- regular user - this will skip subvolumes that are not accessible
- root (CAP_SYS_ADMIN) - no limitations

Pull-request: #861
Signed-off-by: Mark Harmstone <maharmstone@meta.com>
Co-authored-by: Omar Sandoval <osandov@osandov.com>
Reviewed-by: Qu Wenruo <wqu@suse.com>
[ Add details to man page, fix indent in the doc. ]
Signed-off-by: Qu Wenruo <wqu@suse.com>
Signed-off-by: David Sterba <dsterba@suse.com>
  • Loading branch information
2 people authored and kdave committed Nov 8, 2024
1 parent 8859114 commit afd02e4
Show file tree
Hide file tree
Showing 2 changed files with 23 additions and 2 deletions.
9 changes: 9 additions & 0 deletions Documentation/btrfs-subvolume.rst
Original file line number Diff line number Diff line change
Expand Up @@ -112,6 +112,15 @@ delete [options] [<subvolume> [<subvolume>...]], delete -i|--subvolid <subvolid>
-i|--subvolid <subvolid>
subvolume id to be removed instead of the <path> that should point to the
filesystem with the subvolume

-R|--recursive
delete subvolumes beneath each subvolume recursively

This requires either `CAP_SYS_ADMIN` or the filesystem must be
mounted with `user_subvol_rm_allowed` mount option.
In the unprivileged case, subvolumes which cannot be accessed
are skipped. The deletion is not atomic.

-v|--verbose
(deprecated) alias for global *-v* option

Expand Down
16 changes: 14 additions & 2 deletions cmds/subvolume.c
Original file line number Diff line number Diff line change
Expand Up @@ -347,6 +347,8 @@ static const char * const cmd_subvolume_delete_usage[] = {
OPTLINE("-c|--commit-after", "wait for transaction commit at the end of the operation"),
OPTLINE("-C|--commit-each", "wait for transaction commit after deleting each subvolume"),
OPTLINE("-i|--subvolid", "subvolume id of the to be removed subvolume"),
OPTLINE("-R|--recursive", "delete accessible subvolumes beneath each subvolume recursively, "
"this is not atomic, may need root to delete subvolumes not accessible by the user"),
OPTLINE("-v|--verbose", "deprecated, alias for global -v option"),
HELPINFO_INSERT_GLOBALS,
HELPINFO_INSERT_VERBOSE,
Expand All @@ -367,6 +369,7 @@ static int cmd_subvolume_delete(const struct cmd_struct *cmd, int argc, char **a
char *path = NULL;
int commit_mode = 0;
bool subvol_path_not_found = false;
int flags = 0;
u8 fsid[BTRFS_FSID_SIZE];
u64 subvolid = 0;
char uuidbuf[BTRFS_UUID_UNPARSED_SIZE];
Expand All @@ -383,11 +386,12 @@ static int cmd_subvolume_delete(const struct cmd_struct *cmd, int argc, char **a
{"commit-after", no_argument, NULL, 'c'},
{"commit-each", no_argument, NULL, 'C'},
{"subvolid", required_argument, NULL, 'i'},
{"recursive", no_argument, NULL, 'R'},
{"verbose", no_argument, NULL, 'v'},
{NULL, 0, NULL, 0}
};

c = getopt_long(argc, argv, "cCi:v", long_options, NULL);
c = getopt_long(argc, argv, "cCi:Rv", long_options, NULL);
if (c < 0)
break;

Expand All @@ -401,6 +405,9 @@ static int cmd_subvolume_delete(const struct cmd_struct *cmd, int argc, char **a
case 'i':
subvolid = arg_strtou64(optarg);
break;
case 'R':
flags |= BTRFS_UTIL_DELETE_SUBVOLUME_RECURSIVE;
break;
case 'v':
bconf_be_verbose();
break;
Expand All @@ -416,6 +423,11 @@ static int cmd_subvolume_delete(const struct cmd_struct *cmd, int argc, char **a
if (subvolid > 0 && check_argc_exact(argc - optind, 1))
return 1;

if (subvolid > 0 && flags & BTRFS_UTIL_DELETE_SUBVOLUME_RECURSIVE) {
error("option --recursive is not supported with --subvolid");
return 1;
}

pr_verbose(LOG_INFO, "Transaction commit: %s\n",
!commit_mode ? "none (default)" :
commit_mode == COMMIT_AFTER ? "at the end" : "after each");
Expand Down Expand Up @@ -528,7 +540,7 @@ static int cmd_subvolume_delete(const struct cmd_struct *cmd, int argc, char **a

/* Start deleting. */
if (subvolid == 0)
err = btrfs_util_delete_subvolume_fd(fd, vname, 0);
err = btrfs_util_delete_subvolume_fd(fd, vname, flags);
else
err = btrfs_util_delete_subvolume_by_id_fd(fd, subvolid);
if (err) {
Expand Down

0 comments on commit afd02e4

Please sign in to comment.