mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/kdave/btrfs-progs.git
synced 2024-11-16 08:44:31 +08:00
btrfs-progs: add quota group verify code
This patch adds functionality (in qgroup-verify.c) to compute bytecounts in subvolume quota groups. The original groups are read in and stored in memory so that after we compute our own bytecounts, we can compare them with those on disk. A print function is provided to do this comparison and show the results on the console. A 'qgroup check' pass is added to btrfsck. If any subvolume quota groups differ from what we compute, the differences for them are printed. We also provide an option '--qgroup-report' which will run only the quota check code and print a report on all quota groups. Other than making it possible to verify that our qgroup changes work correctly, this mode can also be used in xfstests for automated checking after qgroup tests. This patch does not address the following: - compressed counts are identical to non compressed, because kernel doesn't make the distinction yet. Adding the code to verify compressed counts shouldn't be hard at all though once kernel can do this. - It is only concerned with subvolume quota groups (like most of btrfs-progs). Signed-off-by: Mark Fasheh <mfasheh@suse.de> Signed-off-by: David Sterba <dsterba@suse.cz>
This commit is contained in:
parent
2ab405af95
commit
96ec888aad
2
Makefile
2
Makefile
@ -10,7 +10,7 @@ objects = ctree.o disk-io.o radix-tree.o extent-tree.o print-tree.o \
|
||||
root-tree.o dir-item.o file-item.o inode-item.o inode-map.o \
|
||||
extent-cache.o extent_io.o volumes.o utils.o repair.o \
|
||||
qgroup.o raid6.o free-space-cache.o list_sort.o props.o \
|
||||
utils-lib.o ulist.o
|
||||
utils-lib.o ulist.o qgroup-verify.o
|
||||
cmds_objects = cmds-subvolume.o cmds-filesystem.o cmds-device.o cmds-scrub.o \
|
||||
cmds-inspect.o cmds-balance.o cmds-send.o cmds-receive.o \
|
||||
cmds-quota.o cmds-qgroup.o cmds-replace.o cmds-check.o \
|
||||
|
24
cmds-check.c
24
cmds-check.c
@ -38,6 +38,7 @@
|
||||
#include "commands.h"
|
||||
#include "free-space-cache.h"
|
||||
#include "btrfsck.h"
|
||||
#include "qgroup-verify.h"
|
||||
|
||||
static u64 bytes_used = 0;
|
||||
static u64 total_csum_bytes = 0;
|
||||
@ -6428,6 +6429,7 @@ static struct option long_options[] = {
|
||||
{ "init-csum-tree", 0, NULL, 0 },
|
||||
{ "init-extent-tree", 0, NULL, 0 },
|
||||
{ "backup", 0, NULL, 0 },
|
||||
{ "qgroup-report", 0, NULL, 'Q' },
|
||||
{ NULL, 0, NULL, 0}
|
||||
};
|
||||
|
||||
@ -6440,6 +6442,7 @@ const char * const cmd_check_usage[] = {
|
||||
"--repair try to repair the filesystem",
|
||||
"--init-csum-tree create a new CRC tree",
|
||||
"--init-extent-tree create a new extent tree",
|
||||
"--qgroup-report print a report on qgroup consistency",
|
||||
NULL
|
||||
};
|
||||
|
||||
@ -6454,6 +6457,7 @@ int cmd_check(int argc, char **argv)
|
||||
u64 num;
|
||||
int option_index = 0;
|
||||
int init_csum_tree = 0;
|
||||
int qgroup_report = 0;
|
||||
enum btrfs_open_ctree_flags ctree_flags =
|
||||
OPEN_CTREE_PARTIAL | OPEN_CTREE_EXCLUSIVE;
|
||||
|
||||
@ -6480,6 +6484,9 @@ int cmd_check(int argc, char **argv)
|
||||
printf("using SB copy %llu, bytenr %llu\n", num,
|
||||
(unsigned long long)bytenr);
|
||||
break;
|
||||
case 'Q':
|
||||
qgroup_report = 1;
|
||||
break;
|
||||
case '?':
|
||||
case 'h':
|
||||
usage(cmd_check_usage);
|
||||
@ -6527,6 +6534,14 @@ int cmd_check(int argc, char **argv)
|
||||
|
||||
root = info->fs_root;
|
||||
uuid_unparse(info->super_copy->fsid, uuidbuf);
|
||||
if (qgroup_report) {
|
||||
printf("Print quota groups for %s\nUUID: %s\n", argv[optind],
|
||||
uuidbuf);
|
||||
ret = qgroup_verify_all(info);
|
||||
if (ret == 0)
|
||||
print_qgroup_report(1);
|
||||
goto close_out;
|
||||
}
|
||||
printf("Checking filesystem on %s\nUUID: %s\n", argv[optind], uuidbuf);
|
||||
|
||||
if (!extent_buffer_uptodate(info->tree_root->node) ||
|
||||
@ -6630,11 +6645,20 @@ int cmd_check(int argc, char **argv)
|
||||
free(bad);
|
||||
}
|
||||
|
||||
if (info->quota_enabled) {
|
||||
int err;
|
||||
fprintf(stderr, "checking quota groups\n");
|
||||
err = qgroup_verify_all(info);
|
||||
if (err)
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (!list_empty(&root->fs_info->recow_ebs)) {
|
||||
fprintf(stderr, "Transid errors in file system\n");
|
||||
ret = 1;
|
||||
}
|
||||
out:
|
||||
print_qgroup_report(0);
|
||||
if (found_old_backref) { /*
|
||||
* there was a disk format change when mixed
|
||||
* backref was in testing tree. The old format
|
||||
|
10
ctree.h
10
ctree.h
@ -943,6 +943,7 @@ struct btrfs_fs_info {
|
||||
struct btrfs_root *chunk_root;
|
||||
struct btrfs_root *dev_root;
|
||||
struct btrfs_root *csum_root;
|
||||
struct btrfs_root *quota_root;
|
||||
|
||||
struct rb_root fs_root_tree;
|
||||
|
||||
@ -988,6 +989,7 @@ struct btrfs_fs_info {
|
||||
unsigned int readonly:1;
|
||||
unsigned int on_restoring:1;
|
||||
unsigned int is_chunk_recover:1;
|
||||
unsigned int quota_enabled:1;
|
||||
|
||||
int (*free_extent_hook)(struct btrfs_trans_handle *trans,
|
||||
struct btrfs_root *root,
|
||||
@ -2382,4 +2384,12 @@ int btrfs_csum_truncate(struct btrfs_trans_handle *trans,
|
||||
int btrfs_lookup_uuid_subvol_item(int fd, const u8 *uuid, u64 *subvol_id);
|
||||
int btrfs_lookup_uuid_received_subvol_item(int fd, const u8 *uuid,
|
||||
u64 *subvol_id);
|
||||
|
||||
static inline int is_fstree(u64 rootid)
|
||||
{
|
||||
if (rootid == BTRFS_FS_TREE_OBJECTID ||
|
||||
(signed long long)rootid >= (signed long long)BTRFS_FIRST_FREE_OBJECTID)
|
||||
return 1;
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
16
disk-io.c
16
disk-io.c
@ -569,7 +569,6 @@ static int find_and_setup_log_root(struct btrfs_root *tree_root,
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int btrfs_free_fs_root(struct btrfs_root *root)
|
||||
{
|
||||
if (root->node)
|
||||
@ -695,6 +694,8 @@ struct btrfs_root *btrfs_read_fs_root(struct btrfs_fs_info *fs_info,
|
||||
return fs_info->dev_root;
|
||||
if (location->objectid == BTRFS_CSUM_TREE_OBJECTID)
|
||||
return fs_info->csum_root;
|
||||
if (location->objectid == BTRFS_QUOTA_TREE_OBJECTID)
|
||||
return fs_info->csum_root;
|
||||
|
||||
BUG_ON(location->objectid == BTRFS_TREE_RELOC_OBJECTID ||
|
||||
location->offset != (u64)-1);
|
||||
@ -721,6 +722,7 @@ void btrfs_free_fs_info(struct btrfs_fs_info *fs_info)
|
||||
free(fs_info->chunk_root);
|
||||
free(fs_info->dev_root);
|
||||
free(fs_info->csum_root);
|
||||
free(fs_info->quota_root);
|
||||
free(fs_info->super_copy);
|
||||
free(fs_info->log_root_tree);
|
||||
free(fs_info);
|
||||
@ -741,11 +743,13 @@ struct btrfs_fs_info *btrfs_new_fs_info(int writable, u64 sb_bytenr)
|
||||
fs_info->chunk_root = malloc(sizeof(struct btrfs_root));
|
||||
fs_info->dev_root = malloc(sizeof(struct btrfs_root));
|
||||
fs_info->csum_root = malloc(sizeof(struct btrfs_root));
|
||||
fs_info->quota_root = malloc(sizeof(struct btrfs_root));
|
||||
fs_info->super_copy = malloc(BTRFS_SUPER_INFO_SIZE);
|
||||
|
||||
if (!fs_info->tree_root || !fs_info->extent_root ||
|
||||
!fs_info->chunk_root || !fs_info->dev_root ||
|
||||
!fs_info->csum_root || !fs_info->super_copy)
|
||||
!fs_info->csum_root || !fs_info->quota_root ||
|
||||
!fs_info->super_copy)
|
||||
goto free_all;
|
||||
|
||||
memset(fs_info->super_copy, 0, BTRFS_SUPER_INFO_SIZE);
|
||||
@ -754,6 +758,7 @@ struct btrfs_fs_info *btrfs_new_fs_info(int writable, u64 sb_bytenr)
|
||||
memset(fs_info->chunk_root, 0, sizeof(struct btrfs_root));
|
||||
memset(fs_info->dev_root, 0, sizeof(struct btrfs_root));
|
||||
memset(fs_info->csum_root, 0, sizeof(struct btrfs_root));
|
||||
memset(fs_info->quota_root, 0, sizeof(struct btrfs_root));
|
||||
|
||||
extent_io_tree_init(&fs_info->extent_cache);
|
||||
extent_io_tree_init(&fs_info->free_space_cache);
|
||||
@ -912,6 +917,11 @@ int btrfs_setup_all_roots(struct btrfs_fs_info *fs_info, u64 root_tree_bytenr,
|
||||
}
|
||||
fs_info->csum_root->track_dirty = 1;
|
||||
|
||||
ret = find_and_setup_root(root, fs_info, BTRFS_QUOTA_TREE_OBJECTID,
|
||||
fs_info->quota_root);
|
||||
if (ret == 0)
|
||||
fs_info->quota_enabled = 1;
|
||||
|
||||
ret = find_and_setup_log_root(root, fs_info, sb);
|
||||
if (ret) {
|
||||
printk("Couldn't setup log root tree\n");
|
||||
@ -936,6 +946,8 @@ int btrfs_setup_all_roots(struct btrfs_fs_info *fs_info, u64 root_tree_bytenr,
|
||||
|
||||
void btrfs_release_all_roots(struct btrfs_fs_info *fs_info)
|
||||
{
|
||||
if (fs_info->quota_root)
|
||||
free_extent_buffer(fs_info->quota_root->node);
|
||||
if (fs_info->csum_root)
|
||||
free_extent_buffer(fs_info->csum_root->node);
|
||||
if (fs_info->dev_root)
|
||||
|
@ -251,7 +251,7 @@ static void print_file_extent_item(struct extent_buffer *eb,
|
||||
btrfs_file_extent_compression(eb, fi));
|
||||
}
|
||||
|
||||
static void print_extent_item(struct extent_buffer *eb, int slot, int metadata)
|
||||
void print_extent_item(struct extent_buffer *eb, int slot, int metadata)
|
||||
{
|
||||
struct btrfs_extent_item *ei;
|
||||
struct btrfs_extent_inline_ref *iref;
|
||||
|
@ -22,4 +22,5 @@ void btrfs_print_leaf(struct btrfs_root *root, struct extent_buffer *l);
|
||||
void btrfs_print_tree(struct btrfs_root *root, struct extent_buffer *t, int follow);
|
||||
void btrfs_print_key(struct btrfs_disk_key *disk_key);
|
||||
void print_chunk(struct extent_buffer *eb, struct btrfs_chunk *chunk);
|
||||
void print_extent_item(struct extent_buffer *eb, int slot, int metadata);
|
||||
#endif
|
||||
|
1085
qgroup-verify.c
Normal file
1085
qgroup-verify.c
Normal file
File diff suppressed because it is too large
Load Diff
25
qgroup-verify.h
Normal file
25
qgroup-verify.h
Normal file
@ -0,0 +1,25 @@
|
||||
/*
|
||||
* Copyright (C) 2014 SUSE. All rights reserved.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public
|
||||
* License v2 as published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public
|
||||
* License along with this program; if not, write to the
|
||||
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
|
||||
* Boston, MA 021110-1307, USA.
|
||||
*/
|
||||
|
||||
#ifndef _BTRFS_QGROUP_VERIFY_H
|
||||
#define _BTRFS_QGROUP_VERIFY_H
|
||||
|
||||
int qgroup_verify_all(struct btrfs_fs_info *info);
|
||||
void print_qgroup_report(int all);
|
||||
|
||||
#endif /* _BTRFS_QGROUP_VERIFY_H */
|
Loading…
Reference in New Issue
Block a user