Skip to content

Commit 82f7d6c

Browse files
adam900710kdave
authored andcommitted
btrfs-progs: qgroup: handle stale qgroup deletion more accurately
The current stale qgroup deletion doesn't handle the following cases at all: - It doesn't detect stale qgroups correctly The current check is using the root backref, which means unlinked but not yet fully dropped subvolumes would mark its corresponding qgroups stale. This is incorrect. The real stale check should be based on the root item, not root backref. - Squota non-empty but stale qgroups Such qgroups can not and should not be deleted, as future accounting still require them. - Full accounting mode, stale qgroups but not empty Since qgroup numbers are inconsistent already, it's common to have such stale qgroups with non-zero numbers. Now it's dependent on the kernel to determine whether such qgroup can be deleted. Address the above problems: - Do root_item based detection So that btrfs_qgroup::stale would properly indicate if there is a subvolume root item for the qgroup. - Do not attempt to delete squota stale but non-empty qgroups - Attempt to delete stale but non-empty qgroups for full accounting mode And deletion failure would not count as an error. Signed-off-by: Qu Wenruo <wqu@suse.com> Signed-off-by: David Sterba <dsterba@suse.com>
1 parent 468bbb6 commit 82f7d6c

File tree

1 file changed

+103
-16
lines changed

1 file changed

+103
-16
lines changed

cmds/qgroup.c

Lines changed: 103 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -80,9 +80,23 @@ struct btrfs_qgroup {
8080
struct rb_node all_parent_node;
8181
u64 qgroupid;
8282

83-
/* NULL for qgroups with level > 0 */
83+
/*
84+
* NULL for qgroups with level > 0 or the subvolume is unlinked.
85+
*
86+
* An unlinked subvolume doesn't mean it has been fully dropped, so
87+
* callers should not rely on this to determine if a qgroup is stale.
88+
*
89+
* This member is only to help locating the path of the corresponding
90+
* subvolume.
91+
*/
8492
const char *path;
8593

94+
/*
95+
* This is only true if the qgroup is level 0 qgroup, and there is
96+
* no subvolume tree for the qgroup at all.
97+
*/
98+
bool stale;
99+
86100
/*
87101
* info_item
88102
*/
@@ -229,6 +243,13 @@ static struct {
229243
static btrfs_qgroup_filter_func all_filter_funcs[];
230244
static btrfs_qgroup_comp_func all_comp_funcs[];
231245

246+
static bool is_qgroup_empty(const struct btrfs_qgroup *qg)
247+
{
248+
return !(qg->info.referenced || qg->info.exclusive ||
249+
qg->info.referenced_compressed ||
250+
qg->info.exclusive_compressed);
251+
}
252+
232253
static void qgroup_setup_print_column(enum btrfs_qgroup_column_enum column)
233254
{
234255
int i;
@@ -795,14 +816,31 @@ static struct btrfs_qgroup *get_or_add_qgroup(int fd,
795816
uret = btrfs_util_subvolume_path_fd(fd, qgroupid, &path);
796817
if (uret == BTRFS_UTIL_OK)
797818
bq->path = path;
798-
/* Ignore stale qgroup items */
799819
else if (uret != BTRFS_UTIL_ERROR_SUBVOLUME_NOT_FOUND) {
800820
error("%s", btrfs_util_strerror(uret));
801821
if (uret == BTRFS_UTIL_ERROR_NO_MEMORY)
802822
return ERR_PTR(-ENOMEM);
803823
else
804824
return ERR_PTR(-EIO);
805825
}
826+
/*
827+
* Do a correct stale detection by searching for the ROOT_ITEM of
828+
* the subvolume.
829+
*
830+
* Passing @subvol as NULL will force the search to only search
831+
* for the ROOT_ITEM.
832+
*/
833+
uret = btrfs_util_subvolume_info_fd(fd, qgroupid, NULL);
834+
if (uret == BTRFS_UTIL_OK) {
835+
bq->stale = false;
836+
} else if (uret == BTRFS_UTIL_ERROR_SUBVOLUME_NOT_FOUND) {
837+
bq->stale = true;
838+
} else {
839+
warning("failed to search root item for qgroup %u/%llu, assuming it not stale",
840+
btrfs_qgroup_level(qgroupid),
841+
btrfs_qgroup_subvolid(qgroupid));
842+
bq->stale = false;
843+
}
806844
}
807845

808846
ret = qgroup_tree_insert(qgroup_lookup, bq);
@@ -2136,6 +2174,65 @@ static const char * const cmd_qgroup_clear_stale_usage[] = {
21362174
NULL
21372175
};
21382176

2177+
/*
2178+
* Return >0 if the qgroup should or can not be deleted.
2179+
* Return 0 if the qgroup is deleted.
2180+
* Return <0 for critical error.
2181+
*/
2182+
static int delete_one_stale_qgroup(struct qgroup_lookup *lookup,
2183+
struct btrfs_qgroup *qg, int fd)
2184+
{
2185+
u16 level = btrfs_qgroup_level(qg->qgroupid);
2186+
struct btrfs_ioctl_qgroup_create_args args = { .create = false };
2187+
const bool inconsistent = (lookup->flags & BTRFS_QGROUP_STATUS_FLAG_INCONSISTENT);
2188+
const bool squota = (lookup->flags & BTRFS_QGROUP_STATUS_FLAG_SIMPLE_MODE);
2189+
const bool empty = is_qgroup_empty(qg);
2190+
bool attempt = false;
2191+
int ret;
2192+
2193+
if (level || !qg->stale)
2194+
return 1;
2195+
2196+
/*
2197+
* By design, squota can have a subvolume fully dropped but its qgroup
2198+
* numbers are not zero. Such qgroup is still needed for future
2199+
* accounting, thus can not be deleted.
2200+
*/
2201+
if (squota && !empty)
2202+
return 1;
2203+
2204+
/*
2205+
* We can have inconsistent qgroup numbers, in that case a really stale
2206+
* qgroup can exist while its numbers are not zero.
2207+
*
2208+
* In this case we only attempt to delete the qgroup, depending on the
2209+
* kernel implementation, we may or may not be able to delete it.
2210+
*/
2211+
if (inconsistent && !empty)
2212+
attempt = true;
2213+
2214+
if (attempt)
2215+
pr_verbose(LOG_DEFAULT,
2216+
"Attempt to delete stale but non-empty qgroup %u/%llu\n",
2217+
level, btrfs_qgroup_subvolid(qg->qgroupid));
2218+
else
2219+
pr_verbose(LOG_DEFAULT, "Delete stale qgroup %u/%llu\n",
2220+
level, btrfs_qgroup_subvolid(qg->qgroupid));
2221+
args.qgroupid = qg->qgroupid;
2222+
ret = ioctl(fd, BTRFS_IOC_QGROUP_CREATE, &args);
2223+
if (ret < 0) {
2224+
if (attempt) {
2225+
warning("not possible to delete non-empty stale qgroup %u/%llu",
2226+
level, btrfs_qgroup_subvolid(qg->qgroupid));
2227+
ret = 1;
2228+
} else {
2229+
error("failed to delete qgroup %u/%llu",
2230+
level, btrfs_qgroup_subvolid(qg->qgroupid));
2231+
}
2232+
}
2233+
return ret;
2234+
}
2235+
21392236
static int cmd_qgroup_clear_stale(const struct cmd_struct *cmd, int argc, char **argv)
21402237
{
21412238
enum btrfs_util_error err;
@@ -2172,22 +2269,12 @@ static int cmd_qgroup_clear_stale(const struct cmd_struct *cmd, int argc, char *
21722269

21732270
node = rb_first(&qgroup_lookup.root);
21742271
while (node) {
2175-
u64 level;
2176-
struct btrfs_ioctl_qgroup_create_args args = { .create = false };
2272+
int ret2;
21772273

21782274
entry = rb_entry(node, struct btrfs_qgroup, rb_node);
2179-
level = btrfs_qgroup_level(entry->qgroupid);
2180-
if (!entry->path && level == 0) {
2181-
pr_verbose(LOG_DEFAULT, "Delete stale qgroup %llu/%llu\n",
2182-
level, btrfs_qgroup_subvolid(entry->qgroupid));
2183-
args.qgroupid = entry->qgroupid;
2184-
ret = ioctl(fd, BTRFS_IOC_QGROUP_CREATE, &args);
2185-
if (ret < 0) {
2186-
error("cannot delete qgroup %llu/%llu: %m",
2187-
level,
2188-
btrfs_qgroup_subvolid(entry->qgroupid));
2189-
}
2190-
}
2275+
ret2 = delete_one_stale_qgroup(&qgroup_lookup, entry, fd);
2276+
if (ret2 < 0 && !ret)
2277+
ret = ret2;
21912278
node = rb_next(node);
21922279
}
21932280

0 commit comments

Comments
 (0)