···17361736 /* list of dirty qgroups to be written at next commit */17371737 struct list_head dirty_qgroups;1738173817391739- /* used by btrfs_qgroup_record_ref for an efficient tree traversal */17391739+ /* used by qgroup for an efficient tree traversal */17401740 u64 qgroup_seq;1741174117421742 /* qgroup rescan items */
-5
fs/btrfs/extent-tree.c
···19811981 u64 refs;19821982 int ret;19831983 int no_quota = node->no_quota;19841984- enum btrfs_qgroup_operation_type type = BTRFS_QGROUP_OPER_ADD_EXCL;1985198419861985 path = btrfs_alloc_path();19871986 if (!path)···20082009 btrfs_item_key_to_cpu(leaf, &key, path->slots[0]);20092010 item = btrfs_item_ptr(leaf, path->slots[0], struct btrfs_extent_item);20102011 refs = btrfs_extent_refs(leaf, item);20112011- if (refs)20122012- type = BTRFS_QGROUP_OPER_ADD_SHARED;20132012 btrfs_set_extent_refs(leaf, item, refs + refs_to_add);20142013 if (extent_op)20152014 __run_delayed_extent_op(extent_op, leaf, item);···61096112 u64 bytenr = node->bytenr;61106113 u64 num_bytes = node->num_bytes;61116114 int last_ref = 0;61126112- enum btrfs_qgroup_operation_type type = BTRFS_QGROUP_OPER_SUB_EXCL;61136115 bool skinny_metadata = btrfs_fs_incompat(root->fs_info,61146116 SKINNY_METADATA);61156117···62896293 refs -= refs_to_drop;6290629462916295 if (refs > 0) {62926292- type = BTRFS_QGROUP_OPER_SUB_SHARED;62936296 if (extent_op)62946297 __run_delayed_extent_op(extent_op, leaf, ei);62956298 /*
+2-862
fs/btrfs/qgroup.c
···3434#include "extent_io.h"3535#include "qgroup.h"36363737+3738/* TODO XXX FIXME3839 * - subvol delete -> delete when ref goes to 0? delete limits also?3940 * - reorganize keys···13881387 return ret;13891388}1390138913911391-static int comp_oper_exist(struct btrfs_qgroup_operation *oper1,13921392- struct btrfs_qgroup_operation *oper2)13931393-{13941394- /*13951395- * Ignore seq and type here, we're looking for any operation13961396- * at all related to this extent on that root.13971397- */13981398- if (oper1->bytenr < oper2->bytenr)13991399- return -1;14001400- if (oper1->bytenr > oper2->bytenr)14011401- return 1;14021402- if (oper1->ref_root < oper2->ref_root)14031403- return -1;14041404- if (oper1->ref_root > oper2->ref_root)14051405- return 1;14061406- return 0;14071407-}14081408-14091409-static int qgroup_oper_exists(struct btrfs_fs_info *fs_info,14101410- struct btrfs_qgroup_operation *oper)14111411-{14121412- struct rb_node *n;14131413- struct btrfs_qgroup_operation *cur;14141414- int cmp;14151415-14161416- spin_lock(&fs_info->qgroup_op_lock);14171417- n = fs_info->qgroup_op_tree.rb_node;14181418- while (n) {14191419- cur = rb_entry(n, struct btrfs_qgroup_operation, n);14201420- cmp = comp_oper_exist(cur, oper);14211421- if (cmp < 0) {14221422- n = n->rb_right;14231423- } else if (cmp) {14241424- n = n->rb_left;14251425- } else {14261426- spin_unlock(&fs_info->qgroup_op_lock);14271427- return -EEXIST;14281428- }14291429- }14301430- spin_unlock(&fs_info->qgroup_op_lock);14311431- return 0;14321432-}14331433-14341434-static int comp_oper(struct btrfs_qgroup_operation *oper1,14351435- struct btrfs_qgroup_operation *oper2)14361436-{14371437- if (oper1->bytenr < oper2->bytenr)14381438- return -1;14391439- if (oper1->bytenr > oper2->bytenr)14401440- return 1;14411441- if (oper1->ref_root < oper2->ref_root)14421442- return -1;14431443- if (oper1->ref_root > oper2->ref_root)14441444- return 1;14451445- if (oper1->seq < oper2->seq)14461446- return -1;14471447- if (oper1->seq > oper2->seq)14481448- return 1;14491449- if (oper1->type < oper2->type)14501450- return -1;14511451- if (oper1->type > oper2->type)14521452- return 1;14531453- return 0;14541454-}14551455-14561456-static int insert_qgroup_oper(struct btrfs_fs_info *fs_info,14571457- struct btrfs_qgroup_operation *oper)14581458-{14591459- struct rb_node **p;14601460- struct rb_node *parent = NULL;14611461- struct btrfs_qgroup_operation *cur;14621462- int cmp;14631463-14641464- spin_lock(&fs_info->qgroup_op_lock);14651465- p = &fs_info->qgroup_op_tree.rb_node;14661466- while (*p) {14671467- parent = *p;14681468- cur = rb_entry(parent, struct btrfs_qgroup_operation, n);14691469- cmp = comp_oper(cur, oper);14701470- if (cmp < 0) {14711471- p = &(*p)->rb_right;14721472- } else if (cmp) {14731473- p = &(*p)->rb_left;14741474- } else {14751475- spin_unlock(&fs_info->qgroup_op_lock);14761476- return -EEXIST;14771477- }14781478- }14791479- rb_link_node(&oper->n, parent, p);14801480- rb_insert_color(&oper->n, &fs_info->qgroup_op_tree);14811481- spin_unlock(&fs_info->qgroup_op_lock);14821482- return 0;14831483-}14841484-14851485-/*14861486- * Record a quota operation for processing later on.14871487- * @trans: the transaction we are adding the delayed op to.14881488- * @fs_info: the fs_info for this fs.14891489- * @ref_root: the root of the reference we are acting on,14901490- * @bytenr: the bytenr we are acting on.14911491- * @num_bytes: the number of bytes in the reference.14921492- * @type: the type of operation this is.14931493- * @mod_seq: do we need to get a sequence number for looking up roots.14941494- *14951495- * We just add it to our trans qgroup_ref_list and carry on and process these14961496- * operations in order at some later point. If the reference root isn't a fs14971497- * root then we don't bother with doing anything.14981498- *14991499- * MUST BE HOLDING THE REF LOCK.15001500- */15011501-int btrfs_qgroup_record_ref(struct btrfs_trans_handle *trans,15021502- struct btrfs_fs_info *fs_info, u64 ref_root,15031503- u64 bytenr, u64 num_bytes,15041504- enum btrfs_qgroup_operation_type type, int mod_seq)15051505-{15061506- struct btrfs_qgroup_operation *oper;15071507- int ret;15081508-15091509- if (!is_fstree(ref_root) || !fs_info->quota_enabled)15101510- return 0;15111511-15121512- oper = kmalloc(sizeof(*oper), GFP_NOFS);15131513- if (!oper)15141514- return -ENOMEM;15151515-15161516- oper->ref_root = ref_root;15171517- oper->bytenr = bytenr;15181518- oper->num_bytes = num_bytes;15191519- oper->type = type;15201520- oper->seq = atomic_inc_return(&fs_info->qgroup_op_seq);15211521- INIT_LIST_HEAD(&oper->elem.list);15221522- oper->elem.seq = 0;15231523-15241524- trace_btrfs_qgroup_record_ref(oper);15251525-15261526- if (type == BTRFS_QGROUP_OPER_SUB_SUBTREE) {15271527- /*15281528- * If any operation for this bytenr/ref_root combo15291529- * exists, then we know it's not exclusively owned and15301530- * shouldn't be queued up.15311531- *15321532- * This also catches the case where we have a cloned15331533- * extent that gets queued up multiple times during15341534- * drop snapshot.15351535- */15361536- if (qgroup_oper_exists(fs_info, oper)) {15371537- kfree(oper);15381538- return 0;15391539- }15401540- }15411541-15421542- ret = insert_qgroup_oper(fs_info, oper);15431543- if (ret) {15441544- /* Shouldn't happen so have an assert for developers */15451545- ASSERT(0);15461546- kfree(oper);15471547- return ret;15481548- }15491549- list_add_tail(&oper->list, &trans->qgroup_ref_list);15501550-15511551- if (mod_seq)15521552- btrfs_get_tree_mod_seq(fs_info, &oper->elem);15531553-15541554- return 0;15551555-}15561556-15571390int btrfs_qgroup_prepare_account_extents(struct btrfs_trans_handle *trans,15581391 struct btrfs_fs_info *fs_info)15591392{···14391604 rb_link_node(&record->node, parent_node, p);14401605 rb_insert_color(&record->node, &delayed_refs->dirty_extent_root);14411606 return NULL;14421442-}14431443-14441444-/*14451445- * The easy accounting, if we are adding/removing the only ref for an extent14461446- * then this qgroup and all of the parent qgroups get their refrence and14471447- * exclusive counts adjusted.14481448- */14491449-static int qgroup_excl_accounting(struct btrfs_fs_info *fs_info,14501450- struct btrfs_qgroup_operation *oper)14511451-{14521452- struct ulist *tmp;14531453- int sign = 0;14541454- int ret = 0;14551455-14561456- tmp = ulist_alloc(GFP_NOFS);14571457- if (!tmp)14581458- return -ENOMEM;14591459-14601460- spin_lock(&fs_info->qgroup_lock);14611461- if (!fs_info->quota_root)14621462- goto out;14631463-14641464- switch (oper->type) {14651465- case BTRFS_QGROUP_OPER_ADD_EXCL:14661466- sign = 1;14671467- break;14681468- case BTRFS_QGROUP_OPER_SUB_EXCL:14691469- sign = -1;14701470- break;14711471- default:14721472- ASSERT(0);14731473- }14741474- ret = __qgroup_excl_accounting(fs_info, tmp, oper->ref_root,14751475- oper->num_bytes, sign);14761476-out:14771477- spin_unlock(&fs_info->qgroup_lock);14781478- ulist_free(tmp);14791479- return ret;14801480-}14811481-14821482-/*14831483- * Walk all of the roots that pointed to our bytenr and adjust their refcnts as14841484- * properly.14851485- */14861486-static int qgroup_calc_old_refcnt(struct btrfs_fs_info *fs_info,14871487- u64 root_to_skip, struct ulist *tmp,14881488- struct ulist *roots, struct ulist *qgroups,14891489- u64 seq, int *old_roots, int rescan)14901490-{14911491- struct ulist_node *unode;14921492- struct ulist_iterator uiter;14931493- struct ulist_node *tmp_unode;14941494- struct ulist_iterator tmp_uiter;14951495- struct btrfs_qgroup *qg;14961496- int ret;14971497-14981498- ULIST_ITER_INIT(&uiter);14991499- while ((unode = ulist_next(roots, &uiter))) {15001500- /* We don't count our current root here */15011501- if (unode->val == root_to_skip)15021502- continue;15031503- qg = find_qgroup_rb(fs_info, unode->val);15041504- if (!qg)15051505- continue;15061506- /*15071507- * We could have a pending removal of this same ref so we may15081508- * not have actually found our ref root when doing15091509- * btrfs_find_all_roots, so we need to keep track of how many15101510- * old roots we find in case we removed ours and added a15111511- * different one at the same time. I don't think this could15121512- * happen in practice but that sort of thinking leads to pain15131513- * and suffering and to the dark side.15141514- */15151515- (*old_roots)++;15161516-15171517- ulist_reinit(tmp);15181518- ret = ulist_add(qgroups, qg->qgroupid, ptr_to_u64(qg),15191519- GFP_ATOMIC);15201520- if (ret < 0)15211521- return ret;15221522- ret = ulist_add(tmp, qg->qgroupid, ptr_to_u64(qg), GFP_ATOMIC);15231523- if (ret < 0)15241524- return ret;15251525- ULIST_ITER_INIT(&tmp_uiter);15261526- while ((tmp_unode = ulist_next(tmp, &tmp_uiter))) {15271527- struct btrfs_qgroup_list *glist;15281528- int mod;15291529-15301530- qg = u64_to_ptr(tmp_unode->aux);15311531- /*15321532- * We use this sequence number to keep from having to15331533- * run the whole list and 0 out the refcnt every time.15341534- * We basically use sequnce as the known 0 count and15351535- * then add 1 everytime we see a qgroup. This is how we15361536- * get how many of the roots actually point up to the15371537- * upper level qgroups in order to determine exclusive15381538- * counts.15391539- *15401540- * For rescan none of the extent is recorded before so15411541- * we just don't add old_refcnt.15421542- */15431543- if (rescan)15441544- mod = 0;15451545- else15461546- mod = 1;15471547- btrfs_qgroup_update_old_refcnt(qg, seq, mod);15481548- btrfs_qgroup_update_new_refcnt(qg, seq, 1);15491549- list_for_each_entry(glist, &qg->groups, next_group) {15501550- ret = ulist_add(qgroups, glist->group->qgroupid,15511551- ptr_to_u64(glist->group),15521552- GFP_ATOMIC);15531553- if (ret < 0)15541554- return ret;15551555- ret = ulist_add(tmp, glist->group->qgroupid,15561556- ptr_to_u64(glist->group),15571557- GFP_ATOMIC);15581558- if (ret < 0)15591559- return ret;15601560- }15611561- }15621562- }15631563- return 0;15641564-}15651565-15661566-/*15671567- * We need to walk forward in our operation tree and account for any roots that15681568- * were deleted after we made this operation.15691569- */15701570-static int qgroup_account_deleted_refs(struct btrfs_fs_info *fs_info,15711571- struct btrfs_qgroup_operation *oper,15721572- struct ulist *tmp,15731573- struct ulist *qgroups, u64 seq,15741574- int *old_roots)15751575-{15761576- struct ulist_node *unode;15771577- struct ulist_iterator uiter;15781578- struct btrfs_qgroup *qg;15791579- struct btrfs_qgroup_operation *tmp_oper;15801580- struct rb_node *n;15811581- int ret;15821582-15831583- ulist_reinit(tmp);15841584-15851585- /*15861586- * We only walk forward in the tree since we're only interested in15871587- * removals that happened _after_ our operation.15881588- */15891589- spin_lock(&fs_info->qgroup_op_lock);15901590- n = rb_next(&oper->n);15911591- spin_unlock(&fs_info->qgroup_op_lock);15921592- if (!n)15931593- return 0;15941594- tmp_oper = rb_entry(n, struct btrfs_qgroup_operation, n);15951595- while (tmp_oper->bytenr == oper->bytenr) {15961596- /*15971597- * If it's not a removal we don't care, additions work out15981598- * properly with our refcnt tracking.15991599- */16001600- if (tmp_oper->type != BTRFS_QGROUP_OPER_SUB_SHARED &&16011601- tmp_oper->type != BTRFS_QGROUP_OPER_SUB_EXCL)16021602- goto next;16031603- qg = find_qgroup_rb(fs_info, tmp_oper->ref_root);16041604- if (!qg)16051605- goto next;16061606- ret = ulist_add(qgroups, qg->qgroupid, ptr_to_u64(qg),16071607- GFP_ATOMIC);16081608- if (ret) {16091609- if (ret < 0)16101610- return ret;16111611- /*16121612- * We only want to increase old_roots if this qgroup is16131613- * not already in the list of qgroups. If it is already16141614- * there then that means it must have been re-added or16151615- * the delete will be discarded because we had an16161616- * existing ref that we haven't looked up yet. In this16171617- * case we don't want to increase old_roots. So if ret16181618- * == 1 then we know that this is the first time we've16191619- * seen this qgroup and we can bump the old_roots.16201620- */16211621- (*old_roots)++;16221622- ret = ulist_add(tmp, qg->qgroupid, ptr_to_u64(qg),16231623- GFP_ATOMIC);16241624- if (ret < 0)16251625- return ret;16261626- }16271627-next:16281628- spin_lock(&fs_info->qgroup_op_lock);16291629- n = rb_next(&tmp_oper->n);16301630- spin_unlock(&fs_info->qgroup_op_lock);16311631- if (!n)16321632- break;16331633- tmp_oper = rb_entry(n, struct btrfs_qgroup_operation, n);16341634- }16351635-16361636- /* Ok now process the qgroups we found */16371637- ULIST_ITER_INIT(&uiter);16381638- while ((unode = ulist_next(tmp, &uiter))) {16391639- struct btrfs_qgroup_list *glist;16401640-16411641- qg = u64_to_ptr(unode->aux);16421642- btrfs_qgroup_update_old_refcnt(qg, seq, 1);16431643- btrfs_qgroup_update_new_refcnt(qg, seq, 1);16441644- list_for_each_entry(glist, &qg->groups, next_group) {16451645- ret = ulist_add(qgroups, glist->group->qgroupid,16461646- ptr_to_u64(glist->group), GFP_ATOMIC);16471647- if (ret < 0)16481648- return ret;16491649- ret = ulist_add(tmp, glist->group->qgroupid,16501650- ptr_to_u64(glist->group), GFP_ATOMIC);16511651- if (ret < 0)16521652- return ret;16531653- }16541654- }16551655- return 0;16561656-}16571657-16581658-/* Add refcnt for the newly added reference. */16591659-static int qgroup_calc_new_refcnt(struct btrfs_fs_info *fs_info,16601660- struct btrfs_qgroup_operation *oper,16611661- struct btrfs_qgroup *qgroup,16621662- struct ulist *tmp, struct ulist *qgroups,16631663- u64 seq)16641664-{16651665- struct ulist_node *unode;16661666- struct ulist_iterator uiter;16671667- struct btrfs_qgroup *qg;16681668- int ret;16691669-16701670- ulist_reinit(tmp);16711671- ret = ulist_add(qgroups, qgroup->qgroupid, ptr_to_u64(qgroup),16721672- GFP_ATOMIC);16731673- if (ret < 0)16741674- return ret;16751675- ret = ulist_add(tmp, qgroup->qgroupid, ptr_to_u64(qgroup),16761676- GFP_ATOMIC);16771677- if (ret < 0)16781678- return ret;16791679- ULIST_ITER_INIT(&uiter);16801680- while ((unode = ulist_next(tmp, &uiter))) {16811681- struct btrfs_qgroup_list *glist;16821682-16831683- qg = u64_to_ptr(unode->aux);16841684- if (oper->type == BTRFS_QGROUP_OPER_ADD_SHARED)16851685- btrfs_qgroup_update_new_refcnt(qg, seq, 1);16861686- else16871687- btrfs_qgroup_update_old_refcnt(qg, seq, 1);16881688- list_for_each_entry(glist, &qg->groups, next_group) {16891689- ret = ulist_add(tmp, glist->group->qgroupid,16901690- ptr_to_u64(glist->group), GFP_ATOMIC);16911691- if (ret < 0)16921692- return ret;16931693- ret = ulist_add(qgroups, glist->group->qgroupid,16941694- ptr_to_u64(glist->group), GFP_ATOMIC);16951695- if (ret < 0)16961696- return ret;16971697- }16981698- }16991699- return 0;17001607}1701160817021609#define UPDATE_NEW 0···15021925/*15031926 * Update qgroup rfer/excl counters.15041927 * Rfer update is easy, codes can explain themselves.19281928+ *15051929 * Excl update is tricky, the update is split into 2 part.15061930 * Part 1: Possible exclusive <-> sharing detect:15071931 * | A | !A |···16202042 return 0;16212043}1622204416231623-/*16241624- * This adjusts the counters for all referenced qgroups if need be.16251625- */16261626-static int qgroup_adjust_counters(struct btrfs_fs_info *fs_info,16271627- u64 root_to_skip, u64 num_bytes,16281628- struct ulist *qgroups, u64 seq,16291629- int old_roots, int new_roots, int rescan)16301630-{16311631- struct ulist_node *unode;16321632- struct ulist_iterator uiter;16331633- struct btrfs_qgroup *qg;16341634- u64 cur_new_count, cur_old_count;16351635-16361636- ULIST_ITER_INIT(&uiter);16371637- while ((unode = ulist_next(qgroups, &uiter))) {16381638- bool dirty = false;16391639-16401640- qg = u64_to_ptr(unode->aux);16411641- cur_old_count = btrfs_qgroup_get_old_refcnt(qg, seq);16421642- cur_new_count = btrfs_qgroup_get_new_refcnt(qg, seq);16431643-16441644- /*16451645- * Wasn't referenced before but is now, add to the reference16461646- * counters.16471647- */16481648- if (cur_old_count == 0 && cur_new_count > 0) {16491649- qg->rfer += num_bytes;16501650- qg->rfer_cmpr += num_bytes;16511651- dirty = true;16521652- }16531653-16541654- /*16551655- * Was referenced before but isn't now, subtract from the16561656- * reference counters.16571657- */16581658- if (cur_old_count > 0 && cur_new_count == 0) {16591659- qg->rfer -= num_bytes;16601660- qg->rfer_cmpr -= num_bytes;16611661- dirty = true;16621662- }16631663-16641664- /*16651665- * If our refcount was the same as the roots previously but our16661666- * new count isn't the same as the number of roots now then we16671667- * went from having a exclusive reference on this range to not.16681668- */16691669- if (old_roots && cur_old_count == old_roots &&16701670- (cur_new_count != new_roots || new_roots == 0)) {16711671- WARN_ON(cur_new_count != new_roots && new_roots == 0);16721672- qg->excl -= num_bytes;16731673- qg->excl_cmpr -= num_bytes;16741674- dirty = true;16751675- }16761676-16771677- /*16781678- * If we didn't reference all the roots before but now we do we16791679- * have an exclusive reference to this range.16801680- */16811681- if ((!old_roots || (old_roots && cur_old_count != old_roots))16821682- && cur_new_count == new_roots) {16831683- qg->excl += num_bytes;16841684- qg->excl_cmpr += num_bytes;16851685- dirty = true;16861686- }16871687-16881688- if (dirty)16891689- qgroup_dirty(fs_info, qg);16901690- }16911691- return 0;16921692-}16931693-16941694-/*16951695- * If we removed a data extent and there were other references for that bytenr16961696- * then we need to lookup all referenced roots to make sure we still don't16971697- * reference this bytenr. If we do then we can just discard this operation.16981698- */16991699-static int check_existing_refs(struct btrfs_trans_handle *trans,17001700- struct btrfs_fs_info *fs_info,17011701- struct btrfs_qgroup_operation *oper)17021702-{17031703- struct ulist *roots = NULL;17041704- struct ulist_node *unode;17051705- struct ulist_iterator uiter;17061706- int ret = 0;17071707-17081708- ret = btrfs_find_all_roots(trans, fs_info, oper->bytenr,17091709- oper->elem.seq, &roots);17101710- if (ret < 0)17111711- return ret;17121712- ret = 0;17131713-17141714- ULIST_ITER_INIT(&uiter);17151715- while ((unode = ulist_next(roots, &uiter))) {17161716- if (unode->val == oper->ref_root) {17171717- ret = 1;17181718- break;17191719- }17201720- }17211721- ulist_free(roots);17221722- btrfs_put_tree_mod_seq(fs_info, &oper->elem);17231723-17241724- return ret;17251725-}17261726-17271727-/*17281728- * If we share a reference across multiple roots then we may need to adjust17291729- * various qgroups referenced and exclusive counters. The basic premise is this17301730- *17311731- * 1) We have seq to represent a 0 count. Instead of looping through all of the17321732- * qgroups and resetting their refcount to 0 we just constantly bump this17331733- * sequence number to act as the base reference count. This means that if17341734- * anybody is equal to or below this sequence they were never referenced. We17351735- * jack this sequence up by the number of roots we found each time in order to17361736- * make sure we don't have any overlap.17371737- *17381738- * 2) We first search all the roots that reference the area _except_ the root17391739- * we're acting on currently. This makes up the old_refcnt of all the qgroups17401740- * before.17411741- *17421742- * 3) We walk all of the qgroups referenced by the root we are currently acting17431743- * on, and will either adjust old_refcnt in the case of a removal or the17441744- * new_refcnt in the case of an addition.17451745- *17461746- * 4) Finally we walk all the qgroups that are referenced by this range17471747- * including the root we are acting on currently. We will adjust the counters17481748- * based on the number of roots we had and will have after this operation.17491749- *17501750- * Take this example as an illustration17511751- *17521752- * [qgroup 1/0]17531753- * / | \17541754- * [qg 0/0] [qg 0/1] [qg 0/2]17551755- * \ | /17561756- * [ extent ]17571757- *17581758- * Say we are adding a reference that is covered by qg 0/0. The first step17591759- * would give a refcnt of 1 to qg 0/1 and 0/2 and a refcnt of 2 to qg 1/0 with17601760- * old_roots being 2. Because it is adding new_roots will be 1. We then go17611761- * through qg 0/0 which will get the new_refcnt set to 1 and add 1 to qg 1/0's17621762- * new_refcnt, bringing it to 3. We then walk through all of the qgroups, we17631763- * notice that the old refcnt for qg 0/0 < the new refcnt, so we added a17641764- * reference and thus must add the size to the referenced bytes. Everything17651765- * else is the same so nothing else changes.17661766- */17671767-static int qgroup_shared_accounting(struct btrfs_trans_handle *trans,17681768- struct btrfs_fs_info *fs_info,17691769- struct btrfs_qgroup_operation *oper)17701770-{17711771- struct ulist *roots = NULL;17721772- struct ulist *qgroups, *tmp;17731773- struct btrfs_qgroup *qgroup;17741774- struct seq_list elem = SEQ_LIST_INIT(elem);17751775- u64 seq;17761776- int old_roots = 0;17771777- int new_roots = 0;17781778- int ret = 0;17791779-17801780- if (oper->elem.seq) {17811781- ret = check_existing_refs(trans, fs_info, oper);17821782- if (ret < 0)17831783- return ret;17841784- if (ret)17851785- return 0;17861786- }17871787-17881788- qgroups = ulist_alloc(GFP_NOFS);17891789- if (!qgroups)17901790- return -ENOMEM;17911791-17921792- tmp = ulist_alloc(GFP_NOFS);17931793- if (!tmp) {17941794- ulist_free(qgroups);17951795- return -ENOMEM;17961796- }17971797-17981798- btrfs_get_tree_mod_seq(fs_info, &elem);17991799- ret = btrfs_find_all_roots(trans, fs_info, oper->bytenr, elem.seq,18001800- &roots);18011801- btrfs_put_tree_mod_seq(fs_info, &elem);18021802- if (ret < 0) {18031803- ulist_free(qgroups);18041804- ulist_free(tmp);18051805- return ret;18061806- }18071807- spin_lock(&fs_info->qgroup_lock);18081808- qgroup = find_qgroup_rb(fs_info, oper->ref_root);18091809- if (!qgroup)18101810- goto out;18111811- seq = fs_info->qgroup_seq;18121812-18131813- /*18141814- * So roots is the list of all the roots currently pointing at the18151815- * bytenr, including the ref we are adding if we are adding, or not if18161816- * we are removing a ref. So we pass in the ref_root to skip that root18171817- * in our calculations. We set old_refnct and new_refcnt cause who the18181818- * hell knows what everything looked like before, and it doesn't matter18191819- * except...18201820- */18211821- ret = qgroup_calc_old_refcnt(fs_info, oper->ref_root, tmp, roots, qgroups,18221822- seq, &old_roots, 0);18231823- if (ret < 0)18241824- goto out;18251825-18261826- /*18271827- * Now adjust the refcounts of the qgroups that care about this18281828- * reference, either the old_count in the case of removal or new_count18291829- * in the case of an addition.18301830- */18311831- ret = qgroup_calc_new_refcnt(fs_info, oper, qgroup, tmp, qgroups,18321832- seq);18331833- if (ret < 0)18341834- goto out;18351835-18361836- /*18371837- * ...in the case of removals. If we had a removal before we got around18381838- * to processing this operation then we need to find that guy and count18391839- * his references as if they really existed so we don't end up screwing18401840- * up the exclusive counts. Then whenever we go to process the delete18411841- * everything will be grand and we can account for whatever exclusive18421842- * changes need to be made there. We also have to pass in old_roots so18431843- * we have an accurate count of the roots as it pertains to this18441844- * operations view of the world.18451845- */18461846- ret = qgroup_account_deleted_refs(fs_info, oper, tmp, qgroups, seq,18471847- &old_roots);18481848- if (ret < 0)18491849- goto out;18501850-18511851- /*18521852- * We are adding our root, need to adjust up the number of roots,18531853- * otherwise old_roots is the number of roots we want.18541854- */18551855- if (oper->type == BTRFS_QGROUP_OPER_ADD_SHARED) {18561856- new_roots = old_roots + 1;18571857- } else {18581858- new_roots = old_roots;18591859- old_roots++;18601860- }18611861-18621862- /*18631863- * Bump qgroup_seq to avoid seq overlap18641864- * XXX: This makes qgroup_seq mismatch with oper->seq.18651865- */18661866- fs_info->qgroup_seq += old_roots + 1;18671867-18681868-18691869- /*18701870- * And now the magic happens, bless Arne for having a pretty elegant18711871- * solution for this.18721872- */18731873- qgroup_adjust_counters(fs_info, oper->ref_root, oper->num_bytes,18741874- qgroups, seq, old_roots, new_roots, 0);18751875-out:18761876- spin_unlock(&fs_info->qgroup_lock);18771877- ulist_free(qgroups);18781878- ulist_free(roots);18791879- ulist_free(tmp);18801880- return ret;18811881-}18821882-18831883-/*18841884- * Process a reference to a shared subtree. This type of operation is18851885- * queued during snapshot removal when we encounter extents which are18861886- * shared between more than one root.18871887- */18881888-static int qgroup_subtree_accounting(struct btrfs_trans_handle *trans,18891889- struct btrfs_fs_info *fs_info,18901890- struct btrfs_qgroup_operation *oper)18911891-{18921892- struct ulist *roots = NULL;18931893- struct ulist_node *unode;18941894- struct ulist_iterator uiter;18951895- struct btrfs_qgroup_list *glist;18961896- struct ulist *parents;18971897- int ret = 0;18981898- int err;18991899- struct btrfs_qgroup *qg;19001900- u64 root_obj = 0;19011901- struct seq_list elem = SEQ_LIST_INIT(elem);19021902-19031903- parents = ulist_alloc(GFP_NOFS);19041904- if (!parents)19051905- return -ENOMEM;19061906-19071907- btrfs_get_tree_mod_seq(fs_info, &elem);19081908- ret = btrfs_find_all_roots(trans, fs_info, oper->bytenr,19091909- elem.seq, &roots);19101910- btrfs_put_tree_mod_seq(fs_info, &elem);19111911- if (ret < 0)19121912- goto out;19131913-19141914- if (roots->nnodes != 1)19151915- goto out;19161916-19171917- ULIST_ITER_INIT(&uiter);19181918- unode = ulist_next(roots, &uiter); /* Only want 1 so no need to loop */19191919- /*19201920- * If we find our ref root then that means all refs19211921- * this extent has to the root have not yet been19221922- * deleted. In that case, we do nothing and let the19231923- * last ref for this bytenr drive our update.19241924- *19251925- * This can happen for example if an extent is19261926- * referenced multiple times in a snapshot (clone,19271927- * etc). If we are in the middle of snapshot removal,19281928- * queued updates for such an extent will find the19291929- * root if we have not yet finished removing the19301930- * snapshot.19311931- */19321932- if (unode->val == oper->ref_root)19331933- goto out;19341934-19351935- root_obj = unode->val;19361936- BUG_ON(!root_obj);19371937-19381938- spin_lock(&fs_info->qgroup_lock);19391939- qg = find_qgroup_rb(fs_info, root_obj);19401940- if (!qg)19411941- goto out_unlock;19421942-19431943- qg->excl += oper->num_bytes;19441944- qg->excl_cmpr += oper->num_bytes;19451945- qgroup_dirty(fs_info, qg);19461946-19471947- /*19481948- * Adjust counts for parent groups. First we find all19491949- * parents, then in the 2nd loop we do the adjustment19501950- * while adding parents of the parents to our ulist.19511951- */19521952- list_for_each_entry(glist, &qg->groups, next_group) {19531953- err = ulist_add(parents, glist->group->qgroupid,19541954- ptr_to_u64(glist->group), GFP_ATOMIC);19551955- if (err < 0) {19561956- ret = err;19571957- goto out_unlock;19581958- }19591959- }19601960-19611961- ULIST_ITER_INIT(&uiter);19621962- while ((unode = ulist_next(parents, &uiter))) {19631963- qg = u64_to_ptr(unode->aux);19641964- qg->excl += oper->num_bytes;19651965- qg->excl_cmpr += oper->num_bytes;19661966- qgroup_dirty(fs_info, qg);19671967-19681968- /* Add any parents of the parents */19691969- list_for_each_entry(glist, &qg->groups, next_group) {19701970- err = ulist_add(parents, glist->group->qgroupid,19711971- ptr_to_u64(glist->group), GFP_ATOMIC);19721972- if (err < 0) {19731973- ret = err;19741974- goto out_unlock;19751975- }19761976- }19771977- }19781978-19791979-out_unlock:19801980- spin_unlock(&fs_info->qgroup_lock);19811981-19821982-out:19831983- ulist_free(roots);19841984- ulist_free(parents);19851985- return ret;19861986-}19871987-19881988-/*19891989- * btrfs_qgroup_account_ref is called for every ref that is added to or deleted19901990- * from the fs. First, all roots referencing the extent are searched, and19911991- * then the space is accounted accordingly to the different roots. The19921992- * accounting algorithm works in 3 steps documented inline.19931993- */19941994-static int btrfs_qgroup_account(struct btrfs_trans_handle *trans,19951995- struct btrfs_fs_info *fs_info,19961996- struct btrfs_qgroup_operation *oper)19971997-{19981998- int ret = 0;19991999-20002000- if (!fs_info->quota_enabled)20012001- return 0;20022002-20032003- BUG_ON(!fs_info->quota_root);20042004-20052005- mutex_lock(&fs_info->qgroup_rescan_lock);20062006- if (fs_info->qgroup_flags & BTRFS_QGROUP_STATUS_FLAG_RESCAN) {20072007- if (fs_info->qgroup_rescan_progress.objectid <= oper->bytenr) {20082008- mutex_unlock(&fs_info->qgroup_rescan_lock);20092009- return 0;20102010- }20112011- }20122012- mutex_unlock(&fs_info->qgroup_rescan_lock);20132013-20142014- ASSERT(is_fstree(oper->ref_root));20152015-20162016- trace_btrfs_qgroup_account(oper);20172017-20182018- switch (oper->type) {20192019- case BTRFS_QGROUP_OPER_ADD_EXCL:20202020- case BTRFS_QGROUP_OPER_SUB_EXCL:20212021- ret = qgroup_excl_accounting(fs_info, oper);20222022- break;20232023- case BTRFS_QGROUP_OPER_ADD_SHARED:20242024- case BTRFS_QGROUP_OPER_SUB_SHARED:20252025- ret = qgroup_shared_accounting(trans, fs_info, oper);20262026- break;20272027- case BTRFS_QGROUP_OPER_SUB_SUBTREE:20282028- ret = qgroup_subtree_accounting(trans, fs_info, oper);20292029- break;20302030- default:20312031- ASSERT(0);20322032- }20332033- return ret;20342034-}20352035-20362045int20372046btrfs_qgroup_account_extent(struct btrfs_trans_handle *trans,20382047 struct btrfs_fs_info *fs_info,···17322567 rb_erase(node, &delayed_refs->dirty_extent_root);17332568 kfree(record);1734256917351735- }17361736- return ret;17371737-}17381738-17391739-/*17401740- * Needs to be called everytime we run delayed refs, even if there is an error17411741- * in order to cleanup outstanding operations.17421742- */17431743-int btrfs_delayed_qgroup_accounting(struct btrfs_trans_handle *trans,17441744- struct btrfs_fs_info *fs_info)17451745-{17461746- struct btrfs_qgroup_operation *oper;17471747- int ret = 0;17481748-17491749- while (!list_empty(&trans->qgroup_ref_list)) {17501750- oper = list_first_entry(&trans->qgroup_ref_list,17511751- struct btrfs_qgroup_operation, list);17521752- list_del_init(&oper->list);17531753- if (!ret || !trans->aborted)17541754- ret = btrfs_qgroup_account(trans, fs_info, oper);17551755- spin_lock(&fs_info->qgroup_op_lock);17561756- rb_erase(&oper->n, &fs_info->qgroup_op_tree);17571757- spin_unlock(&fs_info->qgroup_op_lock);17581758- btrfs_put_tree_mod_seq(fs_info, &oper->elem);17591759- kfree(oper);17602570 }17612571 return ret;17622572}
-49
fs/btrfs/qgroup.h
···2323#include "delayed-ref.h"24242525/*2626- * A description of the operations, all of these operations only happen when we2727- * are adding the 1st reference for that subvolume in the case of adding space2828- * or on the last reference delete in the case of subtraction. The only2929- * exception is the last one, which is added for confusion.3030- *3131- * BTRFS_QGROUP_OPER_ADD_EXCL: adding bytes where this subvolume is the only3232- * one pointing at the bytes we are adding. This is called on the first3333- * allocation.3434- *3535- * BTRFS_QGROUP_OPER_ADD_SHARED: adding bytes where this bytenr is going to be3636- * shared between subvols. This is called on the creation of a ref that already3737- * has refs from a different subvolume, so basically reflink.3838- *3939- * BTRFS_QGROUP_OPER_SUB_EXCL: removing bytes where this subvolume is the only4040- * one referencing the range.4141- *4242- * BTRFS_QGROUP_OPER_SUB_SHARED: removing bytes where this subvolume shares with4343- * refs with other subvolumes.4444- */4545-enum btrfs_qgroup_operation_type {4646- BTRFS_QGROUP_OPER_ADD_EXCL,4747- BTRFS_QGROUP_OPER_ADD_SHARED,4848- BTRFS_QGROUP_OPER_SUB_EXCL,4949- BTRFS_QGROUP_OPER_SUB_SHARED,5050- BTRFS_QGROUP_OPER_SUB_SUBTREE,5151-};5252-5353-struct btrfs_qgroup_operation {5454- u64 ref_root;5555- u64 bytenr;5656- u64 num_bytes;5757- u64 seq;5858- enum btrfs_qgroup_operation_type type;5959- struct seq_list elem;6060- struct rb_node n;6161- struct list_head list;6262-};6363-6464-/*6526 * Record a dirty extent, and info qgroup to update quota on it6627 * TODO: Use kmem cache to alloc it.6728 */···5493int btrfs_read_qgroup_config(struct btrfs_fs_info *fs_info);5594void btrfs_free_qgroup_config(struct btrfs_fs_info *fs_info);5695struct btrfs_delayed_extent_op;5757-int btrfs_qgroup_record_ref(struct btrfs_trans_handle *trans,5858- struct btrfs_fs_info *fs_info, u64 ref_root,5959- u64 bytenr, u64 num_bytes,6060- enum btrfs_qgroup_operation_type type,6161- int mod_seq);6296int btrfs_qgroup_prepare_account_extents(struct btrfs_trans_handle *trans,6397 struct btrfs_fs_info *fs_info);6498struct btrfs_qgroup_extent_record···66110 struct ulist *old_roots, struct ulist *new_roots);67111int btrfs_qgroup_account_extents(struct btrfs_trans_handle *trans,68112 struct btrfs_fs_info *fs_info);6969-int btrfs_delayed_qgroup_accounting(struct btrfs_trans_handle *trans,7070- struct btrfs_fs_info *fs_info);7171-void btrfs_remove_qgroup_operation(struct btrfs_trans_handle *trans,7272- struct btrfs_fs_info *fs_info,7373- struct btrfs_qgroup_operation *oper);74113int btrfs_run_qgroups(struct btrfs_trans_handle *trans,75114 struct btrfs_fs_info *fs_info);76115int btrfs_qgroup_inherit(struct btrfs_trans_handle *trans,