qgroup.c (370a11b8114bcca3738fe6a5d7ed8babcc212f39) | qgroup.c (f616f5cd9da7fceb7d884812da380b26040cd083) |
---|---|
1// SPDX-License-Identifier: GPL-2.0 2/* 3 * Copyright (C) 2011 STRATO. All rights reserved. 4 */ 5 6#include <linux/sched.h> 7#include <linux/pagemap.h> 8#include <linux/writeback.h> --- 3954 unchanged lines hidden (view full) --- 3963out_unlock: 3964 spin_unlock(&blocks->lock); 3965out: 3966 if (ret < 0) 3967 fs_info->qgroup_flags |= 3968 BTRFS_QGROUP_STATUS_FLAG_INCONSISTENT; 3969 return ret; 3970} | 1// SPDX-License-Identifier: GPL-2.0 2/* 3 * Copyright (C) 2011 STRATO. All rights reserved. 4 */ 5 6#include <linux/sched.h> 7#include <linux/pagemap.h> 8#include <linux/writeback.h> --- 3954 unchanged lines hidden (view full) --- 3963out_unlock: 3964 spin_unlock(&blocks->lock); 3965out: 3966 if (ret < 0) 3967 fs_info->qgroup_flags |= 3968 BTRFS_QGROUP_STATUS_FLAG_INCONSISTENT; 3969 return ret; 3970} |
3971 3972/* 3973 * Check if the tree block is a subtree root, and if so do the needed 3974 * delayed subtree trace for qgroup. 3975 * 3976 * This is called during btrfs_cow_block(). 3977 */ 3978int btrfs_qgroup_trace_subtree_after_cow(struct btrfs_trans_handle *trans, 3979 struct btrfs_root *root, 3980 struct extent_buffer *subvol_eb) 3981{ 3982 struct btrfs_fs_info *fs_info = root->fs_info; 3983 struct btrfs_qgroup_swapped_blocks *blocks = &root->swapped_blocks; 3984 struct btrfs_qgroup_swapped_block *block; 3985 struct extent_buffer *reloc_eb = NULL; 3986 struct rb_node *node; 3987 bool found = false; 3988 bool swapped = false; 3989 int level = btrfs_header_level(subvol_eb); 3990 int ret = 0; 3991 int i; 3992 3993 if (!test_bit(BTRFS_FS_QUOTA_ENABLED, &fs_info->flags)) 3994 return 0; 3995 if (!is_fstree(root->root_key.objectid) || !root->reloc_root) 3996 return 0; 3997 3998 spin_lock(&blocks->lock); 3999 if (!blocks->swapped) { 4000 spin_unlock(&blocks->lock); 4001 return 0; 4002 } 4003 node = blocks->blocks[level].rb_node; 4004 4005 while (node) { 4006 block = rb_entry(node, struct btrfs_qgroup_swapped_block, node); 4007 if (block->subvol_bytenr < subvol_eb->start) { 4008 node = node->rb_left; 4009 } else if (block->subvol_bytenr > subvol_eb->start) { 4010 node = node->rb_right; 4011 } else { 4012 found = true; 4013 break; 4014 } 4015 } 4016 if (!found) { 4017 spin_unlock(&blocks->lock); 4018 goto out; 4019 } 4020 /* Found one, remove it from @blocks first and update blocks->swapped */ 4021 rb_erase(&block->node, &blocks->blocks[level]); 4022 for (i = 0; i < BTRFS_MAX_LEVEL; i++) { 4023 if (RB_EMPTY_ROOT(&blocks->blocks[i])) { 4024 swapped = true; 4025 break; 4026 } 4027 } 4028 blocks->swapped = swapped; 4029 spin_unlock(&blocks->lock); 4030 4031 /* Read out reloc subtree root */ 4032 reloc_eb = read_tree_block(fs_info, block->reloc_bytenr, 4033 block->reloc_generation, block->level, 4034 &block->first_key); 4035 if (IS_ERR(reloc_eb)) { 4036 ret = PTR_ERR(reloc_eb); 4037 reloc_eb = NULL; 4038 goto free_out; 4039 } 4040 if (!extent_buffer_uptodate(reloc_eb)) { 4041 ret = -EIO; 4042 goto free_out; 4043 } 4044 4045 ret = qgroup_trace_subtree_swap(trans, reloc_eb, subvol_eb, 4046 block->last_snapshot, block->trace_leaf); 4047free_out: 4048 kfree(block); 4049 free_extent_buffer(reloc_eb); 4050out: 4051 if (ret < 0) { 4052 btrfs_err_rl(fs_info, 4053 "failed to account subtree at bytenr %llu: %d", 4054 subvol_eb->start, ret); 4055 fs_info->qgroup_flags |= BTRFS_QGROUP_STATUS_FLAG_INCONSISTENT; 4056 } 4057 return ret; 4058} |
|