qgroup.c 103 KB
Newer Older
1
// SPDX-License-Identifier: GPL-2.0
2
3
4
5
6
7
8
9
10
11
12
/*
 * Copyright (C) 2011 STRATO.  All rights reserved.
 */

#include <linux/sched.h>
#include <linux/pagemap.h>
#include <linux/writeback.h>
#include <linux/blkdev.h>
#include <linux/rbtree.h>
#include <linux/slab.h>
#include <linux/workqueue.h>
13
#include <linux/btrfs.h>
14
#include <linux/sizes.h>
15
16
17
18
19
20
21

#include "ctree.h"
#include "transaction.h"
#include "disk-io.h"
#include "locking.h"
#include "ulist.h"
#include "backref.h"
Jan Schmidt's avatar
Jan Schmidt committed
22
#include "extent_io.h"
Josef Bacik's avatar
Josef Bacik committed
23
#include "qgroup.h"
24
#include "block-group.h"
25

26
27
28
29
30
31
32
/* TODO XXX FIXME
 *  - subvol delete -> delete when ref goes to 0? delete limits also?
 *  - reorganize keys
 *  - compressed
 *  - sync
 *  - copy also limits on subvol creation
 *  - limit
33
 *  - caches for ulists
34
35
36
37
 *  - performance benchmarks
 *  - check all ioctl parameters
 */

38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
/*
 * Helpers to access qgroup reservation
 *
 * Callers should ensure the lock context and type are valid
 */

static u64 qgroup_rsv_total(const struct btrfs_qgroup *qgroup)
{
	u64 ret = 0;
	int i;

	for (i = 0; i < BTRFS_QGROUP_RSV_LAST; i++)
		ret += qgroup->rsv.values[i];

	return ret;
}

#ifdef CONFIG_BTRFS_DEBUG
static const char *qgroup_rsv_type_str(enum btrfs_qgroup_rsv_type type)
{
	if (type == BTRFS_QGROUP_RSV_DATA)
		return "data";
60
61
62
63
	if (type == BTRFS_QGROUP_RSV_META_PERTRANS)
		return "meta_pertrans";
	if (type == BTRFS_QGROUP_RSV_META_PREALLOC)
		return "meta_prealloc";
64
65
66
67
	return NULL;
}
#endif

68
69
static void qgroup_rsv_add(struct btrfs_fs_info *fs_info,
			   struct btrfs_qgroup *qgroup, u64 num_bytes,
70
71
			   enum btrfs_qgroup_rsv_type type)
{
72
	trace_qgroup_update_reserve(fs_info, qgroup, num_bytes, type);
73
74
75
	qgroup->rsv.values[type] += num_bytes;
}

76
77
static void qgroup_rsv_release(struct btrfs_fs_info *fs_info,
			       struct btrfs_qgroup *qgroup, u64 num_bytes,
78
79
			       enum btrfs_qgroup_rsv_type type)
{
80
	trace_qgroup_update_reserve(fs_info, qgroup, -(s64)num_bytes, type);
81
82
83
84
85
86
87
88
89
90
91
92
93
	if (qgroup->rsv.values[type] >= num_bytes) {
		qgroup->rsv.values[type] -= num_bytes;
		return;
	}
#ifdef CONFIG_BTRFS_DEBUG
	WARN_RATELIMIT(1,
		"qgroup %llu %s reserved space underflow, have %llu to free %llu",
		qgroup->qgroupid, qgroup_rsv_type_str(type),
		qgroup->rsv.values[type], num_bytes);
#endif
	qgroup->rsv.values[type] = 0;
}

94
95
96
static void qgroup_rsv_add_by_qgroup(struct btrfs_fs_info *fs_info,
				     struct btrfs_qgroup *dest,
				     struct btrfs_qgroup *src)
97
98
99
100
{
	int i;

	for (i = 0; i < BTRFS_QGROUP_RSV_LAST; i++)
101
		qgroup_rsv_add(fs_info, dest, src->rsv.values[i], i);
102
103
}

104
105
static void qgroup_rsv_release_by_qgroup(struct btrfs_fs_info *fs_info,
					 struct btrfs_qgroup *dest,
106
107
108
109
110
					  struct btrfs_qgroup *src)
{
	int i;

	for (i = 0; i < BTRFS_QGROUP_RSV_LAST; i++)
111
		qgroup_rsv_release(fs_info, dest, src->rsv.values[i], i);
112
113
}

114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
static void btrfs_qgroup_update_old_refcnt(struct btrfs_qgroup *qg, u64 seq,
					   int mod)
{
	if (qg->old_refcnt < seq)
		qg->old_refcnt = seq;
	qg->old_refcnt += mod;
}

static void btrfs_qgroup_update_new_refcnt(struct btrfs_qgroup *qg, u64 seq,
					   int mod)
{
	if (qg->new_refcnt < seq)
		qg->new_refcnt = seq;
	qg->new_refcnt += mod;
}

static inline u64 btrfs_qgroup_get_old_refcnt(struct btrfs_qgroup *qg, u64 seq)
{
	if (qg->old_refcnt < seq)
		return 0;
	return qg->old_refcnt - seq;
}

static inline u64 btrfs_qgroup_get_new_refcnt(struct btrfs_qgroup *qg, u64 seq)
{
	if (qg->new_refcnt < seq)
		return 0;
	return qg->new_refcnt - seq;
}

144
145
146
147
148
149
150
151
152
153
/*
 * glue structure to represent the relations between qgroups.
 */
struct btrfs_qgroup_list {
	struct list_head next_group;
	struct list_head next_member;
	struct btrfs_qgroup *group;
	struct btrfs_qgroup *member;
};

154
155
156
157
158
159
160
161
162
static inline u64 qgroup_to_aux(struct btrfs_qgroup *qg)
{
	return (u64)(uintptr_t)qg;
}

static inline struct btrfs_qgroup* unode_aux_to_qgroup(struct ulist_node *n)
{
	return (struct btrfs_qgroup *)(uintptr_t)n->aux;
}
Josef Bacik's avatar
Josef Bacik committed
163

164
165
166
167
static int
qgroup_rescan_init(struct btrfs_fs_info *fs_info, u64 progress_objectid,
		   int init_flags);
static void qgroup_rescan_zero_tracking(struct btrfs_fs_info *fs_info);
Jan Schmidt's avatar
Jan Schmidt committed
168

169
/* must be called with qgroup_ioctl_lock held */
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
static struct btrfs_qgroup *find_qgroup_rb(struct btrfs_fs_info *fs_info,
					   u64 qgroupid)
{
	struct rb_node *n = fs_info->qgroup_tree.rb_node;
	struct btrfs_qgroup *qgroup;

	while (n) {
		qgroup = rb_entry(n, struct btrfs_qgroup, node);
		if (qgroup->qgroupid < qgroupid)
			n = n->rb_left;
		else if (qgroup->qgroupid > qgroupid)
			n = n->rb_right;
		else
			return qgroup;
	}
	return NULL;
}

/* must be called with qgroup_lock held */
static struct btrfs_qgroup *add_qgroup_rb(struct btrfs_fs_info *fs_info,
					  u64 qgroupid)
{
	struct rb_node **p = &fs_info->qgroup_tree.rb_node;
	struct rb_node *parent = NULL;
	struct btrfs_qgroup *qgroup;

	while (*p) {
		parent = *p;
		qgroup = rb_entry(parent, struct btrfs_qgroup, node);

		if (qgroup->qgroupid < qgroupid)
			p = &(*p)->rb_left;
		else if (qgroup->qgroupid > qgroupid)
			p = &(*p)->rb_right;
		else
			return qgroup;
	}

	qgroup = kzalloc(sizeof(*qgroup), GFP_ATOMIC);
	if (!qgroup)
		return ERR_PTR(-ENOMEM);

	qgroup->qgroupid = qgroupid;
	INIT_LIST_HEAD(&qgroup->groups);
	INIT_LIST_HEAD(&qgroup->members);
	INIT_LIST_HEAD(&qgroup->dirty);

	rb_link_node(&qgroup->node, parent, p);
	rb_insert_color(&qgroup->node, &fs_info->qgroup_tree);

	return qgroup;
}

223
static void __del_qgroup_rb(struct btrfs_qgroup *qgroup)
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
{
	struct btrfs_qgroup_list *list;

	list_del(&qgroup->dirty);
	while (!list_empty(&qgroup->groups)) {
		list = list_first_entry(&qgroup->groups,
					struct btrfs_qgroup_list, next_group);
		list_del(&list->next_group);
		list_del(&list->next_member);
		kfree(list);
	}

	while (!list_empty(&qgroup->members)) {
		list = list_first_entry(&qgroup->members,
					struct btrfs_qgroup_list, next_member);
		list_del(&list->next_group);
		list_del(&list->next_member);
		kfree(list);
	}
	kfree(qgroup);
244
}
245

246
247
248
249
250
251
252
253
254
255
/* must be called with qgroup_lock held */
static int del_qgroup_rb(struct btrfs_fs_info *fs_info, u64 qgroupid)
{
	struct btrfs_qgroup *qgroup = find_qgroup_rb(fs_info, qgroupid);

	if (!qgroup)
		return -ENOENT;

	rb_erase(&qgroup->node, &fs_info->qgroup_tree);
	__del_qgroup_rb(qgroup);
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
	return 0;
}

/* must be called with qgroup_lock held */
static int add_relation_rb(struct btrfs_fs_info *fs_info,
			   u64 memberid, u64 parentid)
{
	struct btrfs_qgroup *member;
	struct btrfs_qgroup *parent;
	struct btrfs_qgroup_list *list;

	member = find_qgroup_rb(fs_info, memberid);
	parent = find_qgroup_rb(fs_info, parentid);
	if (!member || !parent)
		return -ENOENT;

	list = kzalloc(sizeof(*list), GFP_ATOMIC);
	if (!list)
		return -ENOMEM;

	list->group = parent;
	list->member = member;
	list_add_tail(&list->next_group, &member->groups);
	list_add_tail(&list->next_member, &parent->members);

	return 0;
}

/* must be called with qgroup_lock held */
static int del_relation_rb(struct btrfs_fs_info *fs_info,
			   u64 memberid, u64 parentid)
{
	struct btrfs_qgroup *member;
	struct btrfs_qgroup *parent;
	struct btrfs_qgroup_list *list;

	member = find_qgroup_rb(fs_info, memberid);
	parent = find_qgroup_rb(fs_info, parentid);
	if (!member || !parent)
		return -ENOENT;

	list_for_each_entry(list, &member->groups, next_group) {
		if (list->group == parent) {
			list_del(&list->next_group);
			list_del(&list->next_member);
			kfree(list);
			return 0;
		}
	}
	return -ENOENT;
}

308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
#ifdef CONFIG_BTRFS_FS_RUN_SANITY_TESTS
int btrfs_verify_qgroup_counts(struct btrfs_fs_info *fs_info, u64 qgroupid,
			       u64 rfer, u64 excl)
{
	struct btrfs_qgroup *qgroup;

	qgroup = find_qgroup_rb(fs_info, qgroupid);
	if (!qgroup)
		return -EINVAL;
	if (qgroup->rfer != rfer || qgroup->excl != excl)
		return -EINVAL;
	return 0;
}
#endif

323
324
325
326
327
328
329
330
331
332
333
334
335
336
/*
 * The full config is read in one go, only called from open_ctree()
 * It doesn't use any locking, as at this point we're still single-threaded
 */
int btrfs_read_qgroup_config(struct btrfs_fs_info *fs_info)
{
	struct btrfs_key key;
	struct btrfs_key found_key;
	struct btrfs_root *quota_root = fs_info->quota_root;
	struct btrfs_path *path = NULL;
	struct extent_buffer *l;
	int slot;
	int ret = 0;
	u64 flags = 0;
337
	u64 rescan_progress = 0;
338

339
	if (!test_bit(BTRFS_FS_QUOTA_ENABLED, &fs_info->flags))
340
341
		return 0;

342
	fs_info->qgroup_ulist = ulist_alloc(GFP_KERNEL);
343
344
345
346
347
	if (!fs_info->qgroup_ulist) {
		ret = -ENOMEM;
		goto out;
	}

348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
	path = btrfs_alloc_path();
	if (!path) {
		ret = -ENOMEM;
		goto out;
	}

	/* default this to quota off, in case no status key is found */
	fs_info->qgroup_flags = 0;

	/*
	 * pass 1: read status, all qgroup infos and limits
	 */
	key.objectid = 0;
	key.type = 0;
	key.offset = 0;
	ret = btrfs_search_slot_for_read(quota_root, &key, path, 1, 1);
	if (ret)
		goto out;

	while (1) {
		struct btrfs_qgroup *qgroup;

		slot = path->slots[0];
		l = path->nodes[0];
		btrfs_item_key_to_cpu(l, &found_key, slot);

		if (found_key.type == BTRFS_QGROUP_STATUS_KEY) {
			struct btrfs_qgroup_status_item *ptr;

			ptr = btrfs_item_ptr(l, slot,
					     struct btrfs_qgroup_status_item);

			if (btrfs_qgroup_status_version(l, ptr) !=
			    BTRFS_QGROUP_STATUS_VERSION) {
382
383
				btrfs_err(fs_info,
				 "old qgroup version, quota disabled");
384
385
386
387
388
				goto out;
			}
			if (btrfs_qgroup_status_generation(l, ptr) !=
			    fs_info->generation) {
				flags |= BTRFS_QGROUP_STATUS_FLAG_INCONSISTENT;
389
				btrfs_err(fs_info,
Jeff Mahoney's avatar
Jeff Mahoney committed
390
					"qgroup generation mismatch, marked as inconsistent");
391
392
393
			}
			fs_info->qgroup_flags = btrfs_qgroup_status_flags(l,
									  ptr);
394
			rescan_progress = btrfs_qgroup_status_rescan(l, ptr);
395
396
397
398
399
400
401
402
403
404
			goto next1;
		}

		if (found_key.type != BTRFS_QGROUP_INFO_KEY &&
		    found_key.type != BTRFS_QGROUP_LIMIT_KEY)
			goto next1;

		qgroup = find_qgroup_rb(fs_info, found_key.offset);
		if ((qgroup && found_key.type == BTRFS_QGROUP_INFO_KEY) ||
		    (!qgroup && found_key.type == BTRFS_QGROUP_LIMIT_KEY)) {
405
			btrfs_err(fs_info, "inconsistent qgroup config");
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
			flags |= BTRFS_QGROUP_STATUS_FLAG_INCONSISTENT;
		}
		if (!qgroup) {
			qgroup = add_qgroup_rb(fs_info, found_key.offset);
			if (IS_ERR(qgroup)) {
				ret = PTR_ERR(qgroup);
				goto out;
			}
		}
		switch (found_key.type) {
		case BTRFS_QGROUP_INFO_KEY: {
			struct btrfs_qgroup_info_item *ptr;

			ptr = btrfs_item_ptr(l, slot,
					     struct btrfs_qgroup_info_item);
			qgroup->rfer = btrfs_qgroup_info_rfer(l, ptr);
			qgroup->rfer_cmpr = btrfs_qgroup_info_rfer_cmpr(l, ptr);
			qgroup->excl = btrfs_qgroup_info_excl(l, ptr);
			qgroup->excl_cmpr = btrfs_qgroup_info_excl_cmpr(l, ptr);
			/* generation currently unused */
			break;
		}
		case BTRFS_QGROUP_LIMIT_KEY: {
			struct btrfs_qgroup_limit_item *ptr;

			ptr = btrfs_item_ptr(l, slot,
					     struct btrfs_qgroup_limit_item);
			qgroup->lim_flags = btrfs_qgroup_limit_flags(l, ptr);
			qgroup->max_rfer = btrfs_qgroup_limit_max_rfer(l, ptr);
			qgroup->max_excl = btrfs_qgroup_limit_max_excl(l, ptr);
			qgroup->rsv_rfer = btrfs_qgroup_limit_rsv_rfer(l, ptr);
			qgroup->rsv_excl = btrfs_qgroup_limit_rsv_excl(l, ptr);
			break;
		}
		}
next1:
		ret = btrfs_next_item(quota_root, path);
		if (ret < 0)
			goto out;
		if (ret)
			break;
	}
	btrfs_release_path(path);

	/*
	 * pass 2: read all qgroup relations
	 */
	key.objectid = 0;
	key.type = BTRFS_QGROUP_RELATION_KEY;
	key.offset = 0;
	ret = btrfs_search_slot_for_read(quota_root, &key, path, 1, 0);
	if (ret)
		goto out;
	while (1) {
		slot = path->slots[0];
		l = path->nodes[0];
		btrfs_item_key_to_cpu(l, &found_key, slot);

		if (found_key.type != BTRFS_QGROUP_RELATION_KEY)
			goto next2;

		if (found_key.objectid > found_key.offset) {
			/* parent <- member, not needed to build config */
			/* FIXME should we omit the key completely? */
			goto next2;
		}

		ret = add_relation_rb(fs_info, found_key.objectid,
				      found_key.offset);
475
		if (ret == -ENOENT) {
476
477
			btrfs_warn(fs_info,
				"orphan qgroup relation 0x%llx->0x%llx",
478
				found_key.objectid, found_key.offset);
479
480
			ret = 0;	/* ignore the error */
		}
481
482
483
484
485
486
487
488
489
490
491
		if (ret)
			goto out;
next2:
		ret = btrfs_next_item(quota_root, path);
		if (ret < 0)
			goto out;
		if (ret)
			break;
	}
out:
	fs_info->qgroup_flags |= flags;
492
493
494
495
	if (!(fs_info->qgroup_flags & BTRFS_QGROUP_STATUS_FLAG_ON))
		clear_bit(BTRFS_FS_QUOTA_ENABLED, &fs_info->flags);
	else if (fs_info->qgroup_flags & BTRFS_QGROUP_STATUS_FLAG_RESCAN &&
		 ret >= 0)
496
		ret = qgroup_rescan_init(fs_info, rescan_progress, 0);
497
498
	btrfs_free_path(path);

499
	if (ret < 0) {
500
		ulist_free(fs_info->qgroup_ulist);
501
		fs_info->qgroup_ulist = NULL;
502
		fs_info->qgroup_flags &= ~BTRFS_QGROUP_STATUS_FLAG_RESCAN;
503
	}
504

505
506
507
508
	return ret < 0 ? ret : 0;
}

/*
509
510
511
512
 * This is called from close_ctree() or open_ctree() or btrfs_quota_disable(),
 * first two are in single-threaded paths.And for the third one, we have set
 * quota_root to be null with qgroup_lock held before, so it is safe to clean
 * up the in-memory structures without qgroup_lock held.
513
514
515
516
517
518
519
520
521
 */
void btrfs_free_qgroup_config(struct btrfs_fs_info *fs_info)
{
	struct rb_node *n;
	struct btrfs_qgroup *qgroup;

	while ((n = rb_first(&fs_info->qgroup_tree))) {
		qgroup = rb_entry(n, struct btrfs_qgroup, node);
		rb_erase(n, &fs_info->qgroup_tree);
522
		__del_qgroup_rb(qgroup);
523
	}
524
	/*
525
	 * We call btrfs_free_qgroup_config() when unmounting
526
	 * filesystem and disabling quota, so we set qgroup_ulist
527
528
	 * to be null here to avoid double free.
	 */
529
	ulist_free(fs_info->qgroup_ulist);
530
	fs_info->qgroup_ulist = NULL;
531
532
}

533
534
static int add_qgroup_relation_item(struct btrfs_trans_handle *trans, u64 src,
				    u64 dst)
535
536
{
	int ret;
537
	struct btrfs_root *quota_root = trans->fs_info->quota_root;
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
	struct btrfs_path *path;
	struct btrfs_key key;

	path = btrfs_alloc_path();
	if (!path)
		return -ENOMEM;

	key.objectid = src;
	key.type = BTRFS_QGROUP_RELATION_KEY;
	key.offset = dst;

	ret = btrfs_insert_empty_item(trans, quota_root, path, &key, 0);

	btrfs_mark_buffer_dirty(path->nodes[0]);

	btrfs_free_path(path);
	return ret;
}

557
558
static int del_qgroup_relation_item(struct btrfs_trans_handle *trans, u64 src,
				    u64 dst)
559
560
{
	int ret;
561
	struct btrfs_root *quota_root = trans->fs_info->quota_root;
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
	struct btrfs_path *path;
	struct btrfs_key key;

	path = btrfs_alloc_path();
	if (!path)
		return -ENOMEM;

	key.objectid = src;
	key.type = BTRFS_QGROUP_RELATION_KEY;
	key.offset = dst;

	ret = btrfs_search_slot(trans, quota_root, &key, path, -1, 1);
	if (ret < 0)
		goto out;

	if (ret > 0) {
		ret = -ENOENT;
		goto out;
	}

	ret = btrfs_del_item(trans, quota_root, path);
out:
	btrfs_free_path(path);
	return ret;
}

static int add_qgroup_item(struct btrfs_trans_handle *trans,
			   struct btrfs_root *quota_root, u64 qgroupid)
{
	int ret;
	struct btrfs_path *path;
	struct btrfs_qgroup_info_item *qgroup_info;
	struct btrfs_qgroup_limit_item *qgroup_limit;
	struct extent_buffer *leaf;
	struct btrfs_key key;

598
	if (btrfs_is_testing(quota_root->fs_info))
599
		return 0;
600

601
602
603
604
605
606
607
608
	path = btrfs_alloc_path();
	if (!path)
		return -ENOMEM;

	key.objectid = 0;
	key.type = BTRFS_QGROUP_INFO_KEY;
	key.offset = qgroupid;

609
610
611
612
613
614
	/*
	 * Avoid a transaction abort by catching -EEXIST here. In that
	 * case, we proceed by re-initializing the existing structure
	 * on disk.
	 */

615
616
	ret = btrfs_insert_empty_item(trans, quota_root, path, &key,
				      sizeof(*qgroup_info));
617
	if (ret && ret != -EEXIST)
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
		goto out;

	leaf = path->nodes[0];
	qgroup_info = btrfs_item_ptr(leaf, path->slots[0],
				 struct btrfs_qgroup_info_item);
	btrfs_set_qgroup_info_generation(leaf, qgroup_info, trans->transid);
	btrfs_set_qgroup_info_rfer(leaf, qgroup_info, 0);
	btrfs_set_qgroup_info_rfer_cmpr(leaf, qgroup_info, 0);
	btrfs_set_qgroup_info_excl(leaf, qgroup_info, 0);
	btrfs_set_qgroup_info_excl_cmpr(leaf, qgroup_info, 0);

	btrfs_mark_buffer_dirty(leaf);

	btrfs_release_path(path);

	key.type = BTRFS_QGROUP_LIMIT_KEY;
	ret = btrfs_insert_empty_item(trans, quota_root, path, &key,
				      sizeof(*qgroup_limit));
636
	if (ret && ret != -EEXIST)
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
		goto out;

	leaf = path->nodes[0];
	qgroup_limit = btrfs_item_ptr(leaf, path->slots[0],
				  struct btrfs_qgroup_limit_item);
	btrfs_set_qgroup_limit_flags(leaf, qgroup_limit, 0);
	btrfs_set_qgroup_limit_max_rfer(leaf, qgroup_limit, 0);
	btrfs_set_qgroup_limit_max_excl(leaf, qgroup_limit, 0);
	btrfs_set_qgroup_limit_rsv_rfer(leaf, qgroup_limit, 0);
	btrfs_set_qgroup_limit_rsv_excl(leaf, qgroup_limit, 0);

	btrfs_mark_buffer_dirty(leaf);

	ret = 0;
out:
	btrfs_free_path(path);
	return ret;
}

656
static int del_qgroup_item(struct btrfs_trans_handle *trans, u64 qgroupid)
657
658
{
	int ret;
659
	struct btrfs_root *quota_root = trans->fs_info->quota_root;
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
	struct btrfs_path *path;
	struct btrfs_key key;

	path = btrfs_alloc_path();
	if (!path)
		return -ENOMEM;

	key.objectid = 0;
	key.type = BTRFS_QGROUP_INFO_KEY;
	key.offset = qgroupid;
	ret = btrfs_search_slot(trans, quota_root, &key, path, -1, 1);
	if (ret < 0)
		goto out;

	if (ret > 0) {
		ret = -ENOENT;
		goto out;
	}

	ret = btrfs_del_item(trans, quota_root, path);
	if (ret)
		goto out;

	btrfs_release_path(path);

	key.type = BTRFS_QGROUP_LIMIT_KEY;
	ret = btrfs_search_slot(trans, quota_root, &key, path, -1, 1);
	if (ret < 0)
		goto out;

	if (ret > 0) {
		ret = -ENOENT;
		goto out;
	}

	ret = btrfs_del_item(trans, quota_root, path);

out:
	btrfs_free_path(path);
	return ret;
}

static int update_qgroup_limit_item(struct btrfs_trans_handle *trans,
703
				    struct btrfs_qgroup *qgroup)
704
{
705
	struct btrfs_root *quota_root = trans->fs_info->quota_root;
706
707
708
709
710
711
712
713
714
	struct btrfs_path *path;
	struct btrfs_key key;
	struct extent_buffer *l;
	struct btrfs_qgroup_limit_item *qgroup_limit;
	int ret;
	int slot;

	key.objectid = 0;
	key.type = BTRFS_QGROUP_LIMIT_KEY;
715
	key.offset = qgroup->qgroupid;
716
717

	path = btrfs_alloc_path();
718
719
720
	if (!path)
		return -ENOMEM;

721
	ret = btrfs_search_slot(trans, quota_root, &key, path, 0, 1);
722
723
724
725
726
727
728
729
	if (ret > 0)
		ret = -ENOENT;

	if (ret)
		goto out;

	l = path->nodes[0];
	slot = path->slots[0];
730
	qgroup_limit = btrfs_item_ptr(l, slot, struct btrfs_qgroup_limit_item);
731
732
733
734
735
	btrfs_set_qgroup_limit_flags(l, qgroup_limit, qgroup->lim_flags);
	btrfs_set_qgroup_limit_max_rfer(l, qgroup_limit, qgroup->max_rfer);
	btrfs_set_qgroup_limit_max_excl(l, qgroup_limit, qgroup->max_excl);
	btrfs_set_qgroup_limit_rsv_rfer(l, qgroup_limit, qgroup->rsv_rfer);
	btrfs_set_qgroup_limit_rsv_excl(l, qgroup_limit, qgroup->rsv_excl);
736
737
738
739
740
741
742
743
744
745
746

	btrfs_mark_buffer_dirty(l);

out:
	btrfs_free_path(path);
	return ret;
}

static int update_qgroup_info_item(struct btrfs_trans_handle *trans,
				   struct btrfs_qgroup *qgroup)
{
747
748
	struct btrfs_fs_info *fs_info = trans->fs_info;
	struct btrfs_root *quota_root = fs_info->quota_root;
749
750
751
752
753
754
755
	struct btrfs_path *path;
	struct btrfs_key key;
	struct extent_buffer *l;
	struct btrfs_qgroup_info_item *qgroup_info;
	int ret;
	int slot;

756
	if (btrfs_is_testing(fs_info))
757
		return 0;
758

759
760
761
762
763
	key.objectid = 0;
	key.type = BTRFS_QGROUP_INFO_KEY;
	key.offset = qgroup->qgroupid;

	path = btrfs_alloc_path();
764
765
766
	if (!path)
		return -ENOMEM;

767
	ret = btrfs_search_slot(trans, quota_root, &key, path, 0, 1);
768
769
770
771
772
773
774
775
	if (ret > 0)
		ret = -ENOENT;

	if (ret)
		goto out;

	l = path->nodes[0];
	slot = path->slots[0];
776
	qgroup_info = btrfs_item_ptr(l, slot, struct btrfs_qgroup_info_item);
777
778
779
780
781
782
783
784
785
786
787
788
789
	btrfs_set_qgroup_info_generation(l, qgroup_info, trans->transid);
	btrfs_set_qgroup_info_rfer(l, qgroup_info, qgroup->rfer);
	btrfs_set_qgroup_info_rfer_cmpr(l, qgroup_info, qgroup->rfer_cmpr);
	btrfs_set_qgroup_info_excl(l, qgroup_info, qgroup->excl);
	btrfs_set_qgroup_info_excl_cmpr(l, qgroup_info, qgroup->excl_cmpr);

	btrfs_mark_buffer_dirty(l);

out:
	btrfs_free_path(path);
	return ret;
}

790
static int update_qgroup_status_item(struct btrfs_trans_handle *trans)
791
{
792
793
	struct btrfs_fs_info *fs_info = trans->fs_info;
	struct btrfs_root *quota_root = fs_info->quota_root;
794
795
796
797
798
799
800
801
802
803
804
805
	struct btrfs_path *path;
	struct btrfs_key key;
	struct extent_buffer *l;
	struct btrfs_qgroup_status_item *ptr;
	int ret;
	int slot;

	key.objectid = 0;
	key.type = BTRFS_QGROUP_STATUS_KEY;
	key.offset = 0;

	path = btrfs_alloc_path();
806
807
808
	if (!path)
		return -ENOMEM;

809
	ret = btrfs_search_slot(trans, quota_root, &key, path, 0, 1);
810
811
812
813
814
815
816
817
818
819
820
	if (ret > 0)
		ret = -ENOENT;

	if (ret)
		goto out;

	l = path->nodes[0];
	slot = path->slots[0];
	ptr = btrfs_item_ptr(l, slot, struct btrfs_qgroup_status_item);
	btrfs_set_qgroup_status_flags(l, ptr, fs_info->qgroup_flags);
	btrfs_set_qgroup_status_generation(l, ptr, trans->transid);
Jan Schmidt's avatar
Jan Schmidt committed
821
822
	btrfs_set_qgroup_status_rescan(l, ptr,
				fs_info->qgroup_rescan_progress.objectid);
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838

	btrfs_mark_buffer_dirty(l);

out:
	btrfs_free_path(path);
	return ret;
}

/*
 * called with qgroup_lock held
 */
static int btrfs_clean_quota_tree(struct btrfs_trans_handle *trans,
				  struct btrfs_root *root)
{
	struct btrfs_path *path;
	struct btrfs_key key;
839
	struct extent_buffer *leaf = NULL;
840
	int ret;
841
	int nr = 0;
842
843
844
845
846

	path = btrfs_alloc_path();
	if (!path)
		return -ENOMEM;

847
848
849
850
851
	path->leave_spinning = 1;

	key.objectid = 0;
	key.offset = 0;
	key.type = 0;
852

853
	while (1) {
854
		ret = btrfs_search_slot(trans, root, &key, path, -1, 1);
855
856
857
858
859
		if (ret < 0)
			goto out;
		leaf = path->nodes[0];
		nr = btrfs_header_nritems(leaf);
		if (!nr)
860
			break;
861
862
863
864
865
866
867
		/*
		 * delete the leaf one by one
		 * since the whole tree is going
		 * to be deleted.
		 */
		path->slots[0] = 0;
		ret = btrfs_del_items(trans, root, path, 0, nr);
868
869
		if (ret)
			goto out;
870

871
872
873
874
875
876
877
878
		btrfs_release_path(path);
	}
	ret = 0;
out:
	btrfs_free_path(path);
	return ret;
}

879
int btrfs_quota_enable(struct btrfs_fs_info *fs_info)
880
881
{
	struct btrfs_root *quota_root;
882
	struct btrfs_root *tree_root = fs_info->tree_root;
883
884
885
886
	struct btrfs_path *path = NULL;
	struct btrfs_qgroup_status_item *ptr;
	struct extent_buffer *leaf;
	struct btrfs_key key;
887
888
	struct btrfs_key found_key;
	struct btrfs_qgroup *qgroup = NULL;
889
	struct btrfs_trans_handle *trans = NULL;
890
	int ret = 0;
891
	int slot;
892

893
	mutex_lock(&fs_info->qgroup_ioctl_lock);
894
	if (fs_info->quota_root)
895
896
		goto out;

897
898
899
900
901
902
	fs_info->qgroup_ulist = ulist_alloc(GFP_KERNEL);
	if (!fs_info->qgroup_ulist) {
		ret = -ENOMEM;
		goto out;
	}

903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
	/*
	 * 1 for quota root item
	 * 1 for BTRFS_QGROUP_STATUS item
	 *
	 * Yet we also need 2*n items for a QGROUP_INFO/QGROUP_LIMIT items
	 * per subvolume. However those are not currently reserved since it
	 * would be a lot of overkill.
	 */
	trans = btrfs_start_transaction(tree_root, 2);
	if (IS_ERR(trans)) {
		ret = PTR_ERR(trans);
		trans = NULL;
		goto out;
	}

918
919
920
	/*
	 * initially create the quota tree
	 */
921
	quota_root = btrfs_create_tree(trans, BTRFS_QUOTA_TREE_OBJECTID);
922
923
	if (IS_ERR(quota_root)) {
		ret =  PTR_ERR(quota_root);
924
		btrfs_abort_transaction(trans, ret);
925
926
927
928
		goto out;
	}

	path = btrfs_alloc_path();
929
930
	if (!path) {
		ret = -ENOMEM;
931
		btrfs_abort_transaction(trans, ret);
932
933
		goto out_free_root;
	}
934
935
936
937
938
939
940

	key.objectid = 0;
	key.type = BTRFS_QGROUP_STATUS_KEY;
	key.offset = 0;

	ret = btrfs_insert_empty_item(trans, quota_root, path, &key,
				      sizeof(*ptr));
941
942
	if (ret) {
		btrfs_abort_transaction(trans, ret);
943
		goto out_free_path;
944
	}
945
946
947
948
949
950
951
952
953

	leaf = path->nodes[0];
	ptr = btrfs_item_ptr(leaf, path->slots[0],
				 struct btrfs_qgroup_status_item);
	btrfs_set_qgroup_status_generation(leaf, ptr, trans->transid);
	btrfs_set_qgroup_status_version(leaf, ptr, BTRFS_QGROUP_STATUS_VERSION);
	fs_info->qgroup_flags = BTRFS_QGROUP_STATUS_FLAG_ON |
				BTRFS_QGROUP_STATUS_FLAG_INCONSISTENT;
	btrfs_set_qgroup_status_flags(leaf, ptr, fs_info->qgroup_flags);
Jan Schmidt's avatar
Jan Schmidt committed
954
	btrfs_set_qgroup_status_rescan(leaf, ptr, 0);
955
956
957

	btrfs_mark_buffer_dirty(leaf);

958
959
960
961
962
963
964
965
	key.objectid = 0;
	key.type = BTRFS_ROOT_REF_KEY;
	key.offset = 0;

	btrfs_release_path(path);
	ret = btrfs_search_slot_for_read(tree_root, &key, path, 1, 0);
	if (ret > 0)
		goto out_add_root;
966
967
	if (ret < 0) {
		btrfs_abort_transaction(trans, ret);
968
		goto out_free_path;
969
	}
970
971
972
973
974
975
976
977
978

	while (1) {
		slot = path->slots[0];
		leaf = path->nodes[0];
		btrfs_item_key_to_cpu(leaf, &found_key, slot);

		if (found_key.type == BTRFS_ROOT_REF_KEY) {
			ret = add_qgroup_item(trans, quota_root,
					      found_key.offset);
979
980
			if (ret) {
				btrfs_abort_transaction(trans, ret);
981
				goto out_free_path;
982
			}
983
984
985
986

			qgroup = add_qgroup_rb(fs_info, found_key.offset);
			if (IS_ERR(qgroup)) {
				ret = PTR_ERR(qgroup);
987
				btrfs_abort_transaction(trans, ret);
988
989
990
991
				goto out_free_path;
			}
		}
		ret = btrfs_next_item(tree_root, path);
992
993
		if (ret < 0) {
			btrfs_abort_transaction(trans, ret);
994
			goto out_free_path;
995
		}
996
997
998
999
1000
1001
1002
		if (ret)
			break;
	}

out_add_root:
	btrfs_release_path(path);
	ret = add_qgroup_item(trans, quota_root, BTRFS_FS_TREE_OBJECTID);
1003
1004
	if (ret) {
		btrfs_abort_transaction(trans, ret);
1005
		goto out_free_path;
1006
	}
1007
1008
1009
1010

	qgroup = add_qgroup_rb(fs_info, BTRFS_FS_TREE_OBJECTID);
	if (IS_ERR(qgroup)) {
		ret = PTR_ERR(qgroup);
1011
		btrfs_abort_transaction(trans, ret);
1012
1013
		goto out_free_path;
	}
1014
1015

	ret = btrfs_commit_transaction(trans);
1016
1017
	trans = NULL;
	if (ret)
1018
1019
		goto out_free_path;

1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
	/*
	 * Set quota enabled flag after committing the transaction, to avoid
	 * deadlocks on fs_info->qgroup_ioctl_lock with concurrent snapshot
	 * creation.
	 */
	spin_lock(&fs_info->qgroup_lock);
	fs_info->quota_root = quota_root;
	set_bit(BTRFS_FS_QUOTA_ENABLED, &fs_info->flags);
	spin_unlock(&fs_info->qgroup_lock);

1030
1031
1032
1033
1034
1035
1036
	ret = qgroup_rescan_init(fs_info, 0, 1);
	if (!ret) {
	        qgroup_rescan_zero_tracking(fs_info);
	        btrfs_queue_work(fs_info->qgroup_rescan_workers,
	                         &fs_info->qgroup_rescan_work);
	}

1037
out_free_path:
1038
	btrfs_free_path(path);
1039
1040
1041
1042
1043
1044
1045
out_free_root:
	if (ret) {
		free_extent_buffer(quota_root->node);
		free_extent_buffer(quota_root->commit_root);
		kfree(quota_root);
	}
out:
1046
	if (ret) {
1047
		ulist_free(fs_info->qgroup_ulist);
1048
		fs_info->qgroup_ulist = NULL;
1049
1050
		if (trans)
			btrfs_end_transaction(trans);
1051
	}
1052
	mutex_unlock(&fs_info->qgroup_ioctl_lock);
1053
1054
1055
	return ret;
}

1056
int btrfs_quota_disable(struct btrfs_fs_info *fs_info)
1057
1058
{
	struct btrfs_root *quota_root;
1059
	struct btrfs_trans_handle *trans = NULL;
1060
1061
	int ret = 0;

1062
	mutex_lock(&fs_info->qgroup_ioctl_lock);
1063
	if (!fs_info->quota_root)
1064
		goto out;
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077

	/*
	 * 1 For the root item
	 *
	 * We should also reserve enough items for the quota tree deletion in
	 * btrfs_clean_quota_tree but this is not done.
	 */
	trans = btrfs_start_transaction(fs_info->tree_root, 1);
	if (IS_ERR(trans)) {
		ret = PTR_ERR(trans);
		goto out;
	}

1078
	clear_bit(BTRFS_FS_QUOTA_ENABLED, &fs_info->flags);
1079
	btrfs_qgroup_wait_for_completion(fs_info, false);
1080
	spin_lock(&fs_info->qgroup_lock);
1081
1082
	quota_root = fs_info->quota_root;
	fs_info->quota_root = NULL;
1083
	fs_info->qgroup_flags &= ~BTRFS_QGROUP_STATUS_FLAG_ON;
1084
1085
	spin_unlock(&fs_info->qgroup_lock);

1086
1087
	btrfs_free_qgroup_config(fs_info);

1088
	ret = btrfs_clean_quota_tree(trans, quota_root);
1089
1090
1091
1092
	if (ret) {
		btrfs_abort_transaction(trans, ret);
		goto end_trans;
	}
1093

1094
	ret = btrfs_del_root(trans, &quota_root->root_key);
1095
1096
1097
1098
	if (ret) {
		btrfs_abort_transaction(trans, ret);
		goto end_trans;
	}
1099
1100
1101
1102

	list_del(&quota_root->dirty_list);

	btrfs_tree_lock(quota_root->node);
1103
	btrfs_clean_tree_block(quota_root->node);
1104
1105
1106
1107
1108
1109
	btrfs_tree_unlock(quota_root->node);
	btrfs_free_tree_block(trans, quota_root, quota_root->node, 0, 1);

	free_extent_buffer(quota_root->node);
	free_extent_buffer(quota_root->commit_root);
	kfree(quota_root);
1110
1111
1112

end_trans:
	ret = btrfs_end_transaction(trans);
1113
out:
1114
	mutex_unlock(&fs_info->qgroup_ioctl_lock);
1115
1116
1117
	return ret;
}

Jan Schmidt's avatar
Jan Schmidt committed
1118
1119
static void qgroup_dirty(struct btrfs_fs_info *fs_info,
			 struct btrfs_qgroup *qgroup)
1120
{
Jan Schmidt's avatar
Jan Schmidt committed
1121
1122
	if (list_empty(&qgroup->dirty))
		list_add(&qgroup->dirty, &fs_info->dirty_qgroups);
1123
1124
}

1125
/*
1126
1127
1128
 * The easy accounting, we're updating qgroup relationship whose child qgroup
 * only has exclusive extents.
 *
1129
 * In this case, all exclusive extents will also be exclusive for parent, so
1130
1131
1132
1133
1134
1135
 * excl/rfer just get added/removed.
 *
 * So is qgroup reservation space, which should also be added/removed to
 * parent.
 * Or when child tries to release reservation space, parent will underflow its
 * reservation (for relationship adding case).
1136
1137
1138
1139
1140
 *
 * Caller should hold fs_info->qgroup_lock.
 */
static int __qgroup_excl_accounting(struct btrfs_fs_info *fs_info,
				    struct ulist *tmp, u64 ref_root,
1141
				    struct btrfs_qgroup *src, int sign)
1142
1143
1144
1145
1146
{
	struct btrfs_qgroup *qgroup;
	struct btrfs_qgroup_list *glist;
	struct ulist_node *unode;
	struct ulist_iterator uiter;
1147
	u64 num_bytes = src->excl;
1148
1149
1150
1151
1152
1153
1154
1155
1156
1157
1158
1159
	int ret = 0;

	qgroup = find_qgroup_rb(fs_info, ref_root);
	if (!qgroup)
		goto out;

	qgroup->rfer += sign * num_bytes;
	qgroup->rfer_cmpr += sign * num_bytes;

	WARN_ON(sign < 0 && qgroup->excl < num_bytes);
	qgroup->excl += sign * num_bytes;
	qgroup->excl_cmpr += sign * num_bytes;
1160
1161

	if (sign > 0)
1162
		qgroup_rsv_add_by_qgroup(fs_info, qgroup, src);
1163
	else
1164
		qgroup_rsv_release_by_qgroup(fs_info, qgroup, src);
1165
1166
1167
1168
1169
1170

	qgroup_dirty(fs_info, qgroup);

	/* Get all of the parent groups that contain this qgroup */
	list_for_each_entry(glist, &qgroup->groups, next_group) {
		ret = ulist_add(tmp, glist->group->qgroupid,
1171
				qgroup_to_aux(glist->group), GFP_ATOMIC);
1172
1173
1174
1175
1176
1177
1178
		if (ret < 0)
			goto out;
	}

	/* Iterate all of the parents and adjust their reference counts */
	ULIST_ITER_INIT(&uiter);
	while ((unode = ulist_next(tmp, &uiter))) {
1179
		qgroup = unode_aux_to_qgroup(unode);
1180
1181
1182
1183
		qgroup->rfer += sign * num_bytes;
		qgroup->rfer_cmpr += sign * num_bytes;
		WARN_ON(sign < 0 && qgroup->excl < num_bytes);
		qgroup->excl += sign * num_bytes;
1184
		if (sign > 0)
1185
			qgroup_rsv_add_by_qgroup(fs_info, qgroup, src);
1186
		else
1187
			qgroup_rsv_release_by_qgroup(fs_info, qgroup, src);
1188
1189
1190
1191
1192
1193
		qgroup->excl_cmpr += sign * num_bytes;
		qgroup_dirty(fs_info, qgroup);

		/* Add any parents of the parents */
		list_for_each_entry(glist, &qgroup->groups, next_group) {
			ret = ulist_add(tmp, glist->group->qgroupid,
1194
					qgroup_to_aux(glist->group), GFP_ATOMIC);
1195
1196
1197
1198
1199
1200
1201
1202
1203
1204
1205
1206
1207
1208
1209
1210
1211
1212
1213
1214
1215
1216
1217
1218
1219
1220
1221
1222
1223
1224
1225
1226
1227
1228
1229
			if (ret < 0)
				goto out;
		}
	}
	ret = 0;
out:
	return ret;
}


/*
 * Quick path for updating qgroup with only excl refs.
 *
 * In that case, just update all parent will be enough.
 * Or we needs to do a full rescan.
 * Caller should also hold fs_info->qgroup_lock.
 *
 * Return 0 for quick update, return >0 for need to full rescan
 * and mark INCONSISTENT flag.
 * Return < 0 for other error.
 */
static int quick_update_accounting(struct btrfs_fs_info *fs_info,
				   struct ulist *tmp, u64 src, u64 dst,
				   int sign)
{
	struct btrfs_qgroup *qgroup;
	int ret = 1;
	int err = 0;

	qgroup = find_qgroup_rb(fs_info, src);
	if (!qgroup)
		goto out;
	if (qgroup->excl == qgroup->rfer) {
		ret = 0;
		err = __qgroup_excl_accounting(fs_info, tmp, dst,
1230
					       qgroup, sign);
1231
1232
1233
1234
1235
1236
1237
1238
1239
1240
1241
		if (err < 0) {
			ret = err;
			goto out;
		}
	}
out:
	if (ret)
		fs_info->qgroup_flags |= BTRFS_QGROUP_STATUS_FLAG_INCONSISTENT;
	return ret;
}

1242
1243
int btrfs_add_qgroup_relation(struct btrfs_trans_handle *trans, u64 src,
			      u64 dst)
1244
{
1245
	struct btrfs_fs_info *fs_info = trans->fs_info;
1246
	struct btrfs_root *quota_root;
1247
1248
	struct btrfs_qgroup *parent;
	struct btrfs_qgroup *member;
1249
	struct btrfs_qgroup_list *list;
1250
	struct ulist *tmp;
1251
1252
	int ret = 0;

1253
1254
1255
1256
	/* Check the level of src and dst first */
	if (btrfs_qgroup_level(src) >= btrfs_qgroup_level(dst))
		return -EINVAL;

1257
	tmp = ulist_alloc(GFP_KERNEL);
1258
1259
1260
	if (!tmp)
		return -ENOMEM;

1261
	mutex_lock(&fs_info->qgroup_ioctl_lock);
1262
	quota_root = fs_info->quota_root;
1263
1264
1265
1266
	if (!quota_root) {
		ret = -EINVAL;
		goto out;
	}
1267
1268
1269
1270
1271
1272
	member = find_qgroup_rb(fs_info, src);
	parent = find_qgroup_rb(fs_info, dst);
	if (!member || !parent) {
		ret = -EINVAL;
		goto out;
	}
1273

1274
1275
1276
1277
1278
1279
1280
1281
	/* check if such qgroup relation exist firstly */
	list_for_each_entry(list, &member->groups, next_group) {
		if (list->group == parent) {
			ret = -EEXIST;
			goto out;
		}
	}

1282
	ret = add_qgroup_relation_item(trans, src, dst);
1283
	if (ret)
1284
		goto out;
1285

1286
	ret = add_qgroup_relation_item(trans, dst, src);
1287
	if (ret) {
1288
		del_qgroup_relation_item(trans, src, dst);
1289
		goto out;
1290
1291
1292
	}

	spin_lock(&fs_info->qgroup_lock);
1293
	ret = add_relation_rb(fs_info, src, dst);
1294
1295
1296
1297
1298
	if (ret < 0) {
		spin_unlock(&fs_info->qgroup_lock);
		goto out;
	}
	ret = quick_update_accounting(fs_info, tmp, src, dst, 1);
1299
	spin_unlock(&fs_info->qgroup_lock);
1300
1301
out:
	mutex_unlock(&fs_info->qgroup_ioctl_lock);
1302
	ulist_free(tmp);
1303
1304
1305
	return ret;
}

1306
1307
static int __del_qgroup_relation(struct btrfs_trans_handle *trans, u64 src,
				 u64 dst)
1308
{
1309
	struct btrfs_fs_info *fs_info = trans->fs_info;
1310
	struct btrfs_root *quota_root;
1311
1312
1313
	struct btrfs_qgroup *parent;
	struct btrfs_qgroup *member;
	struct btrfs_qgroup_list *list;
1314
	struct ulist *tmp;
1315
	bool found = false;
1316
	int ret = 0;
1317
	int ret2;
1318

1319
	tmp = ulist_alloc(GFP_KERNEL);
1320
1321
1322
	if (!tmp)
		return -ENOMEM;

1323
	quota_root = fs_info->quota_root;
1324
1325
1326
1327
	if (!quota_root) {
		ret = -EINVAL;
		goto out;
	}
1328

1329
1330
	member = find_qgroup_rb(fs_info, src);
	parent = find_qgroup_rb(fs_info, dst);
1331
1332
1333
1334
1335
1336
	/*
	 * The parent/member pair doesn't exist, then try to delete the dead
	 * relation items only.
	 */
	if (!member || !parent)
		goto delete_item;
1337
1338
1339

	/* check if such qgroup relation exist firstly */
	list_for_each_entry(list, &member->groups, next_group) {
1340
1341
1342
1343
		if (list->group == parent) {
			found = true;
			break;
		}
1344
	}
1345
1346

delete_item:
1347
	ret = del_qgroup_relation_item(trans, src, dst);
1348
1349
1350
1351
1352
	if (ret < 0 && ret != -ENOENT)
		goto out;
	ret2 = del_qgroup_relation_item(trans, dst, src);
	if (ret2 < 0 && ret2 != -ENOENT)
		goto out;
1353

1354
1355
1356
1357
1358
1359
1360
1361
1362
1363
	/* At least one deletion succeeded, return 0 */
	if (!ret || !ret2)
		ret = 0;

	if (found) {
		spin_lock(&fs_info->qgroup_lock);
		del_relation_rb(fs_info, src, dst);
		ret = quick_update_accounting(fs_info, tmp, src, dst, -1);
		spin_unlock(&fs_info->qgroup_lock);
	}
1364
out:
1365
	ulist_free(tmp);
1366
1367
1368
	return ret;
}

1369
1370
int btrfs_del_qgroup_relation(struct btrfs_trans_handle *trans, u64 src,
			      u64 dst)
1371
{
1372
	struct btrfs_fs_info *fs_info = trans->fs_info;
1373
1374
1375
	int ret = 0;

	mutex_lock(&fs_info->qgroup_ioctl_lock);
1376
	ret = __del_qgroup_relation(trans, src, dst);
1377
	mutex_unlock(&fs_info->qgroup_ioctl_lock);
1378

1379
1380
1381
	return ret;
}

1382
int btrfs_create_qgroup(struct btrfs_trans_handle *trans, u64 qgroupid)
1383
{
1384
	struct btrfs_fs_info *fs_info = trans->fs_info;
1385
1386
1387
1388
	struct btrfs_root *quota_root;
	struct btrfs_qgroup *qgroup;
	int ret = 0;

1389
	mutex_lock(&fs_info->qgroup_ioctl_lock);
1390
	quota_root = fs_info->quota_root;
1391
1392
1393
1394
	if (!quota_root) {
		ret = -EINVAL;
		goto out;
	}
1395
1396
1397
1398
1399
	qgroup = find_qgroup_rb(fs_info, qgroupid);
	if (qgroup) {
		ret = -EEXIST;
		goto out;
	}
1400
1401

	ret = add_qgroup_item<