Blame view

fs/btrfs/qgroup.c 107 KB
c1d7c514f   David Sterba   btrfs: replace GP...
1
  // SPDX-License-Identifier: GPL-2.0
bed92eae2   Arne Jansen   Btrfs: qgroup imp...
2
3
  /*
   * Copyright (C) 2011 STRATO.  All rights reserved.
bed92eae2   Arne Jansen   Btrfs: qgroup imp...
4
5
6
7
8
9
10
11
12
   */
  
  #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>
55e301fd5   Filipe Brandenburger   Btrfs: move fs/bt...
13
  #include <linux/btrfs.h>
bed92eae2   Arne Jansen   Btrfs: qgroup imp...
14
15
16
17
18
19
  
  #include "ctree.h"
  #include "transaction.h"
  #include "disk-io.h"
  #include "locking.h"
  #include "ulist.h"
bed92eae2   Arne Jansen   Btrfs: qgroup imp...
20
  #include "backref.h"
2f2320360   Jan Schmidt   Btrfs: rescan for...
21
  #include "extent_io.h"
fcebe4562   Josef Bacik   Btrfs: rework qgr...
22
  #include "qgroup.h"
aac0023c2   Josef Bacik   btrfs: move basic...
23
  #include "block-group.h"
49e5fb462   Qu Wenruo   btrfs: qgroup: ex...
24
  #include "sysfs.h"
e69bcee37   Qu Wenruo   btrfs: qgroup: Cl...
25

bed92eae2   Arne Jansen   Btrfs: qgroup imp...
26
27
28
29
30
  /* TODO XXX FIXME
   *  - subvol delete -> delete when ref goes to 0? delete limits also?
   *  - reorganize keys
   *  - compressed
   *  - sync
bed92eae2   Arne Jansen   Btrfs: qgroup imp...
31
32
   *  - copy also limits on subvol creation
   *  - limit
52042d8e8   Andrea Gelmini   btrfs: Fix typos ...
33
   *  - caches for ulists
bed92eae2   Arne Jansen   Btrfs: qgroup imp...
34
35
36
   *  - performance benchmarks
   *  - check all ioctl parameters
   */
f59c0347d   Qu Wenruo   btrfs: qgroup: In...
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
  /*
   * 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";
733e03a0b   Qu Wenruo   btrfs: qgroup: Sp...
59
60
61
62
  	if (type == BTRFS_QGROUP_RSV_META_PERTRANS)
  		return "meta_pertrans";
  	if (type == BTRFS_QGROUP_RSV_META_PREALLOC)
  		return "meta_prealloc";
f59c0347d   Qu Wenruo   btrfs: qgroup: In...
63
64
65
  	return NULL;
  }
  #endif
64ee4e751   Qu Wenruo   btrfs: qgroup: Up...
66
67
  static void qgroup_rsv_add(struct btrfs_fs_info *fs_info,
  			   struct btrfs_qgroup *qgroup, u64 num_bytes,
f59c0347d   Qu Wenruo   btrfs: qgroup: In...
68
69
  			   enum btrfs_qgroup_rsv_type type)
  {
64ee4e751   Qu Wenruo   btrfs: qgroup: Up...
70
  	trace_qgroup_update_reserve(fs_info, qgroup, num_bytes, type);
f59c0347d   Qu Wenruo   btrfs: qgroup: In...
71
72
  	qgroup->rsv.values[type] += num_bytes;
  }
64ee4e751   Qu Wenruo   btrfs: qgroup: Up...
73
74
  static void qgroup_rsv_release(struct btrfs_fs_info *fs_info,
  			       struct btrfs_qgroup *qgroup, u64 num_bytes,
f59c0347d   Qu Wenruo   btrfs: qgroup: In...
75
76
  			       enum btrfs_qgroup_rsv_type type)
  {
64ee4e751   Qu Wenruo   btrfs: qgroup: Up...
77
  	trace_qgroup_update_reserve(fs_info, qgroup, -(s64)num_bytes, type);
f59c0347d   Qu Wenruo   btrfs: qgroup: In...
78
79
80
81
82
83
84
85
86
87
88
89
  	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;
  }
64ee4e751   Qu Wenruo   btrfs: qgroup: Up...
90
91
92
  static void qgroup_rsv_add_by_qgroup(struct btrfs_fs_info *fs_info,
  				     struct btrfs_qgroup *dest,
  				     struct btrfs_qgroup *src)
f59c0347d   Qu Wenruo   btrfs: qgroup: In...
93
94
95
96
  {
  	int i;
  
  	for (i = 0; i < BTRFS_QGROUP_RSV_LAST; i++)
64ee4e751   Qu Wenruo   btrfs: qgroup: Up...
97
  		qgroup_rsv_add(fs_info, dest, src->rsv.values[i], i);
f59c0347d   Qu Wenruo   btrfs: qgroup: In...
98
  }
64ee4e751   Qu Wenruo   btrfs: qgroup: Up...
99
100
  static void qgroup_rsv_release_by_qgroup(struct btrfs_fs_info *fs_info,
  					 struct btrfs_qgroup *dest,
f59c0347d   Qu Wenruo   btrfs: qgroup: In...
101
102
103
104
105
  					  struct btrfs_qgroup *src)
  {
  	int i;
  
  	for (i = 0; i < BTRFS_QGROUP_RSV_LAST; i++)
64ee4e751   Qu Wenruo   btrfs: qgroup: Up...
106
  		qgroup_rsv_release(fs_info, dest, src->rsv.values[i], i);
f59c0347d   Qu Wenruo   btrfs: qgroup: In...
107
  }
9c542136f   Qu Wenruo   btrfs: qgroup: Cl...
108
109
110
111
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
  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;
  }
bed92eae2   Arne Jansen   Btrfs: qgroup imp...
137
138
139
140
141
142
143
144
145
  /*
   * 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;
  };
ef2fff64f   David Sterba   btrfs: rename hel...
146
147
148
149
150
151
152
153
154
  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;
  }
fcebe4562   Josef Bacik   Btrfs: rework qgr...
155

b382a324b   Jan Schmidt   Btrfs: fix qgroup...
156
157
158
159
  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);
2f2320360   Jan Schmidt   Btrfs: rescan for...
160

58400fce5   Wang Shilong   Btrfs: remove som...
161
  /* must be called with qgroup_ioctl_lock held */
bed92eae2   Arne Jansen   Btrfs: qgroup imp...
162
163
164
165
166
167
168
169
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
  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;
  }
49e5fb462   Qu Wenruo   btrfs: qgroup: ex...
214
215
  static void __del_qgroup_rb(struct btrfs_fs_info *fs_info,
  			    struct btrfs_qgroup *qgroup)
bed92eae2   Arne Jansen   Btrfs: qgroup imp...
216
  {
bed92eae2   Arne Jansen   Btrfs: qgroup imp...
217
  	struct btrfs_qgroup_list *list;
49e5fb462   Qu Wenruo   btrfs: qgroup: ex...
218
  	btrfs_sysfs_del_one_qgroup(fs_info, qgroup);
bed92eae2   Arne Jansen   Btrfs: qgroup imp...
219
  	list_del(&qgroup->dirty);
bed92eae2   Arne Jansen   Btrfs: qgroup imp...
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
  	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);
4082bd3d7   Wang Shilong   Btrfs: fix oops w...
236
  }
bed92eae2   Arne Jansen   Btrfs: qgroup imp...
237

4082bd3d7   Wang Shilong   Btrfs: fix oops w...
238
239
240
241
242
243
244
245
246
  /* 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);
49e5fb462   Qu Wenruo   btrfs: qgroup: ex...
247
  	__del_qgroup_rb(fs_info, qgroup);
bed92eae2   Arne Jansen   Btrfs: qgroup imp...
248
249
250
251
252
253
254
255
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
  	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;
  }
faa2dbf00   Josef Bacik   Btrfs: add sanity...
299
300
301
302
303
304
305
306
307
308
309
310
311
312
  #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
bed92eae2   Arne Jansen   Btrfs: qgroup imp...
313
314
315
316
317
318
319
320
321
322
323
324
325
326
  /*
   * 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;
b382a324b   Jan Schmidt   Btrfs: fix qgroup...
327
  	u64 rescan_progress = 0;
bed92eae2   Arne Jansen   Btrfs: qgroup imp...
328

afcdd129e   Josef Bacik   Btrfs: add a flag...
329
  	if (!test_bit(BTRFS_FS_QUOTA_ENABLED, &fs_info->flags))
bed92eae2   Arne Jansen   Btrfs: qgroup imp...
330
  		return 0;
323b88f4a   David Sterba   btrfs: use GFP_KE...
331
  	fs_info->qgroup_ulist = ulist_alloc(GFP_KERNEL);
1e8f91586   Wang Shilong   Btrfs: introduce ...
332
333
334
335
  	if (!fs_info->qgroup_ulist) {
  		ret = -ENOMEM;
  		goto out;
  	}
bed92eae2   Arne Jansen   Btrfs: qgroup imp...
336
337
338
339
340
  	path = btrfs_alloc_path();
  	if (!path) {
  		ret = -ENOMEM;
  		goto out;
  	}
49e5fb462   Qu Wenruo   btrfs: qgroup: ex...
341
342
343
  	ret = btrfs_sysfs_add_qgroups(fs_info);
  	if (ret < 0)
  		goto out;
bed92eae2   Arne Jansen   Btrfs: qgroup imp...
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
  	/* 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) {
efe120a06   Frank Holton   Btrfs: convert pr...
372
373
  				btrfs_err(fs_info,
  				 "old qgroup version, quota disabled");
bed92eae2   Arne Jansen   Btrfs: qgroup imp...
374
375
376
377
378
  				goto out;
  			}
  			if (btrfs_qgroup_status_generation(l, ptr) !=
  			    fs_info->generation) {
  				flags |= BTRFS_QGROUP_STATUS_FLAG_INCONSISTENT;
efe120a06   Frank Holton   Btrfs: convert pr...
379
  				btrfs_err(fs_info,
5d163e0e6   Jeff Mahoney   btrfs: unsplit pr...
380
  					"qgroup generation mismatch, marked as inconsistent");
bed92eae2   Arne Jansen   Btrfs: qgroup imp...
381
382
383
  			}
  			fs_info->qgroup_flags = btrfs_qgroup_status_flags(l,
  									  ptr);
b382a324b   Jan Schmidt   Btrfs: fix qgroup...
384
  			rescan_progress = btrfs_qgroup_status_rescan(l, ptr);
bed92eae2   Arne Jansen   Btrfs: qgroup imp...
385
386
387
388
389
390
391
392
393
394
  			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)) {
d41e36a0a   Geert Uytterhoeven   Btrfs: Spelling s...
395
  			btrfs_err(fs_info, "inconsistent qgroup config");
bed92eae2   Arne Jansen   Btrfs: qgroup imp...
396
397
398
399
400
401
402
403
404
  			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;
  			}
  		}
49e5fb462   Qu Wenruo   btrfs: qgroup: ex...
405
406
407
  		ret = btrfs_sysfs_add_one_qgroup(fs_info, qgroup);
  		if (ret < 0)
  			goto out;
bed92eae2   Arne Jansen   Btrfs: qgroup imp...
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
  		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);
ff24858c6   Arne Jansen   Btrfs: ignore orp...
468
  		if (ret == -ENOENT) {
efe120a06   Frank Holton   Btrfs: convert pr...
469
470
  			btrfs_warn(fs_info,
  				"orphan qgroup relation 0x%llx->0x%llx",
c1c9ff7c9   Geert Uytterhoeven   Btrfs: Remove sup...
471
  				found_key.objectid, found_key.offset);
ff24858c6   Arne Jansen   Btrfs: ignore orp...
472
473
  			ret = 0;	/* ignore the error */
  		}
bed92eae2   Arne Jansen   Btrfs: qgroup imp...
474
475
476
477
478
479
480
481
482
483
484
  		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;
afcdd129e   Josef Bacik   Btrfs: add a flag...
485
486
487
488
  	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)
b382a324b   Jan Schmidt   Btrfs: fix qgroup...
489
  		ret = qgroup_rescan_init(fs_info, rescan_progress, 0);
bed92eae2   Arne Jansen   Btrfs: qgroup imp...
490
  	btrfs_free_path(path);
eb1716af8   Jan Schmidt   Btrfs: avoid doub...
491
  	if (ret < 0) {
1e8f91586   Wang Shilong   Btrfs: introduce ...
492
  		ulist_free(fs_info->qgroup_ulist);
eb1716af8   Jan Schmidt   Btrfs: avoid doub...
493
  		fs_info->qgroup_ulist = NULL;
b382a324b   Jan Schmidt   Btrfs: fix qgroup...
494
  		fs_info->qgroup_flags &= ~BTRFS_QGROUP_STATUS_FLAG_RESCAN;
49e5fb462   Qu Wenruo   btrfs: qgroup: ex...
495
  		btrfs_sysfs_del_qgroups(fs_info);
eb1716af8   Jan Schmidt   Btrfs: avoid doub...
496
  	}
1e8f91586   Wang Shilong   Btrfs: introduce ...
497

bed92eae2   Arne Jansen   Btrfs: qgroup imp...
498
499
  	return ret < 0 ? ret : 0;
  }
5958253cf   Qu Wenruo   btrfs: qgroup: ca...
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
  /*
   * Called in close_ctree() when quota is still enabled.  This verifies we don't
   * leak some reserved space.
   *
   * Return false if no reserved space is left.
   * Return true if some reserved space is leaked.
   */
  bool btrfs_check_quota_leak(struct btrfs_fs_info *fs_info)
  {
  	struct rb_node *node;
  	bool ret = false;
  
  	if (!test_bit(BTRFS_FS_QUOTA_ENABLED, &fs_info->flags))
  		return ret;
  	/*
  	 * Since we're unmounting, there is no race and no need to grab qgroup
  	 * lock.  And here we don't go post-order to provide a more user
  	 * friendly sorted result.
  	 */
  	for (node = rb_first(&fs_info->qgroup_tree); node; node = rb_next(node)) {
  		struct btrfs_qgroup *qgroup;
  		int i;
  
  		qgroup = rb_entry(node, struct btrfs_qgroup, node);
  		for (i = 0; i < BTRFS_QGROUP_RSV_LAST; i++) {
  			if (qgroup->rsv.values[i]) {
  				ret = true;
  				btrfs_warn(fs_info,
06f67c470   Qu Wenruo   btrfs: use __u16 ...
528
  		"qgroup %hu/%llu has unreleased space, type %d rsv %llu",
5958253cf   Qu Wenruo   btrfs: qgroup: ca...
529
530
531
532
533
534
535
536
  				   btrfs_qgroup_level(qgroup->qgroupid),
  				   btrfs_qgroup_subvolid(qgroup->qgroupid),
  				   i, qgroup->rsv.values[i]);
  			}
  		}
  	}
  	return ret;
  }
bed92eae2   Arne Jansen   Btrfs: qgroup imp...
537
  /*
e685da14a   Wang Shilong   Btrfs: move btrfs...
538
539
540
541
   * 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.
bed92eae2   Arne Jansen   Btrfs: qgroup imp...
542
543
544
545
546
   */
  void btrfs_free_qgroup_config(struct btrfs_fs_info *fs_info)
  {
  	struct rb_node *n;
  	struct btrfs_qgroup *qgroup;
bed92eae2   Arne Jansen   Btrfs: qgroup imp...
547
548
549
550
  
  	while ((n = rb_first(&fs_info->qgroup_tree))) {
  		qgroup = rb_entry(n, struct btrfs_qgroup, node);
  		rb_erase(n, &fs_info->qgroup_tree);
49e5fb462   Qu Wenruo   btrfs: qgroup: ex...
551
  		__del_qgroup_rb(fs_info, qgroup);
bed92eae2   Arne Jansen   Btrfs: qgroup imp...
552
  	}
1e7bac1ef   Wang Shilong   Btrfs: set qgroup...
553
  	/*
52042d8e8   Andrea Gelmini   btrfs: Fix typos ...
554
  	 * We call btrfs_free_qgroup_config() when unmounting
013276101   Nicholas D Steeves   btrfs: fix string...
555
  	 * filesystem and disabling quota, so we set qgroup_ulist
1e7bac1ef   Wang Shilong   Btrfs: set qgroup...
556
557
  	 * to be null here to avoid double free.
  	 */
1e8f91586   Wang Shilong   Btrfs: introduce ...
558
  	ulist_free(fs_info->qgroup_ulist);
1e7bac1ef   Wang Shilong   Btrfs: set qgroup...
559
  	fs_info->qgroup_ulist = NULL;
49e5fb462   Qu Wenruo   btrfs: qgroup: ex...
560
  	btrfs_sysfs_del_qgroups(fs_info);
bed92eae2   Arne Jansen   Btrfs: qgroup imp...
561
  }
711169c40   Lu Fengqi   btrfs: qgroup: Dr...
562
563
  static int add_qgroup_relation_item(struct btrfs_trans_handle *trans, u64 src,
  				    u64 dst)
bed92eae2   Arne Jansen   Btrfs: qgroup imp...
564
565
  {
  	int ret;
711169c40   Lu Fengqi   btrfs: qgroup: Dr...
566
  	struct btrfs_root *quota_root = trans->fs_info->quota_root;
bed92eae2   Arne Jansen   Btrfs: qgroup imp...
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
  	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;
  }
99d7f09ac   Lu Fengqi   btrfs: qgroup: Dr...
585
586
  static int del_qgroup_relation_item(struct btrfs_trans_handle *trans, u64 src,
  				    u64 dst)
bed92eae2   Arne Jansen   Btrfs: qgroup imp...
587
588
  {
  	int ret;
99d7f09ac   Lu Fengqi   btrfs: qgroup: Dr...
589
  	struct btrfs_root *quota_root = trans->fs_info->quota_root;
bed92eae2   Arne Jansen   Btrfs: qgroup imp...
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
  	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;
f5ee5c9ac   Jeff Mahoney   btrfs: tests, use...
625
  	if (btrfs_is_testing(quota_root->fs_info))
faa2dbf00   Josef Bacik   Btrfs: add sanity...
626
  		return 0;
fccb84c94   David Sterba   btrfs: move check...
627

bed92eae2   Arne Jansen   Btrfs: qgroup imp...
628
629
630
631
632
633
634
  	path = btrfs_alloc_path();
  	if (!path)
  		return -ENOMEM;
  
  	key.objectid = 0;
  	key.type = BTRFS_QGROUP_INFO_KEY;
  	key.offset = qgroupid;
0b4699dcb   Mark Fasheh   btrfs: don't go r...
635
636
637
638
639
  	/*
  	 * Avoid a transaction abort by catching -EEXIST here. In that
  	 * case, we proceed by re-initializing the existing structure
  	 * on disk.
  	 */
bed92eae2   Arne Jansen   Btrfs: qgroup imp...
640
641
  	ret = btrfs_insert_empty_item(trans, quota_root, path, &key,
  				      sizeof(*qgroup_info));
0b4699dcb   Mark Fasheh   btrfs: don't go r...
642
  	if (ret && ret != -EEXIST)
bed92eae2   Arne Jansen   Btrfs: qgroup imp...
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
  		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));
0b4699dcb   Mark Fasheh   btrfs: don't go r...
661
  	if (ret && ret != -EEXIST)
bed92eae2   Arne Jansen   Btrfs: qgroup imp...
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
  		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;
  }
69104618f   Lu Fengqi   btrfs: qgroup: Dr...
680
  static int del_qgroup_item(struct btrfs_trans_handle *trans, u64 qgroupid)
bed92eae2   Arne Jansen   Btrfs: qgroup imp...
681
682
  {
  	int ret;
69104618f   Lu Fengqi   btrfs: qgroup: Dr...
683
  	struct btrfs_root *quota_root = trans->fs_info->quota_root;
bed92eae2   Arne Jansen   Btrfs: qgroup imp...
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
  	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,
1510e71c6   Dongsheng Yang   btrfs: qgroup: co...
727
  				    struct btrfs_qgroup *qgroup)
bed92eae2   Arne Jansen   Btrfs: qgroup imp...
728
  {
ac8a866af   Lu Fengqi   btrfs: qgroup: Dr...
729
  	struct btrfs_root *quota_root = trans->fs_info->quota_root;
bed92eae2   Arne Jansen   Btrfs: qgroup imp...
730
731
732
733
734
735
736
737
738
  	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;
1510e71c6   Dongsheng Yang   btrfs: qgroup: co...
739
  	key.offset = qgroup->qgroupid;
bed92eae2   Arne Jansen   Btrfs: qgroup imp...
740
741
  
  	path = btrfs_alloc_path();
84cbe2f72   Wang Shilong   Btrfs: return ENO...
742
743
  	if (!path)
  		return -ENOMEM;
ac8a866af   Lu Fengqi   btrfs: qgroup: Dr...
744
  	ret = btrfs_search_slot(trans, quota_root, &key, path, 0, 1);
bed92eae2   Arne Jansen   Btrfs: qgroup imp...
745
746
747
748
749
750
751
752
  	if (ret > 0)
  		ret = -ENOENT;
  
  	if (ret)
  		goto out;
  
  	l = path->nodes[0];
  	slot = path->slots[0];
a3df41ee3   Valentina Giusti   btrfs: fix unused...
753
  	qgroup_limit = btrfs_item_ptr(l, slot, struct btrfs_qgroup_limit_item);
1510e71c6   Dongsheng Yang   btrfs: qgroup: co...
754
755
756
757
758
  	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);
bed92eae2   Arne Jansen   Btrfs: qgroup imp...
759
760
761
762
763
764
765
766
767
  
  	btrfs_mark_buffer_dirty(l);
  
  out:
  	btrfs_free_path(path);
  	return ret;
  }
  
  static int update_qgroup_info_item(struct btrfs_trans_handle *trans,
bed92eae2   Arne Jansen   Btrfs: qgroup imp...
768
769
  				   struct btrfs_qgroup *qgroup)
  {
3e07e9a09   Lu Fengqi   btrfs: qgroup: Dr...
770
771
  	struct btrfs_fs_info *fs_info = trans->fs_info;
  	struct btrfs_root *quota_root = fs_info->quota_root;
bed92eae2   Arne Jansen   Btrfs: qgroup imp...
772
773
774
775
776
777
  	struct btrfs_path *path;
  	struct btrfs_key key;
  	struct extent_buffer *l;
  	struct btrfs_qgroup_info_item *qgroup_info;
  	int ret;
  	int slot;
3e07e9a09   Lu Fengqi   btrfs: qgroup: Dr...
778
  	if (btrfs_is_testing(fs_info))
faa2dbf00   Josef Bacik   Btrfs: add sanity...
779
  		return 0;
fccb84c94   David Sterba   btrfs: move check...
780

bed92eae2   Arne Jansen   Btrfs: qgroup imp...
781
782
783
784
785
  	key.objectid = 0;
  	key.type = BTRFS_QGROUP_INFO_KEY;
  	key.offset = qgroup->qgroupid;
  
  	path = btrfs_alloc_path();
84cbe2f72   Wang Shilong   Btrfs: return ENO...
786
787
  	if (!path)
  		return -ENOMEM;
3e07e9a09   Lu Fengqi   btrfs: qgroup: Dr...
788
  	ret = btrfs_search_slot(trans, quota_root, &key, path, 0, 1);
bed92eae2   Arne Jansen   Btrfs: qgroup imp...
789
790
791
792
793
794
795
796
  	if (ret > 0)
  		ret = -ENOENT;
  
  	if (ret)
  		goto out;
  
  	l = path->nodes[0];
  	slot = path->slots[0];
a3df41ee3   Valentina Giusti   btrfs: fix unused...
797
  	qgroup_info = btrfs_item_ptr(l, slot, struct btrfs_qgroup_info_item);
bed92eae2   Arne Jansen   Btrfs: qgroup imp...
798
799
800
801
802
803
804
805
806
807
808
809
  	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;
  }
2e980acdd   Lu Fengqi   btrfs: qgroup: Dr...
810
  static int update_qgroup_status_item(struct btrfs_trans_handle *trans)
bed92eae2   Arne Jansen   Btrfs: qgroup imp...
811
  {
2e980acdd   Lu Fengqi   btrfs: qgroup: Dr...
812
813
  	struct btrfs_fs_info *fs_info = trans->fs_info;
  	struct btrfs_root *quota_root = fs_info->quota_root;
bed92eae2   Arne Jansen   Btrfs: qgroup imp...
814
815
816
817
818
819
820
821
822
823
824
825
  	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();
84cbe2f72   Wang Shilong   Btrfs: return ENO...
826
827
  	if (!path)
  		return -ENOMEM;
2e980acdd   Lu Fengqi   btrfs: qgroup: Dr...
828
  	ret = btrfs_search_slot(trans, quota_root, &key, path, 0, 1);
bed92eae2   Arne Jansen   Btrfs: qgroup imp...
829
830
831
832
833
834
835
836
837
838
839
  	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);
2f2320360   Jan Schmidt   Btrfs: rescan for...
840
841
  	btrfs_set_qgroup_status_rescan(l, ptr,
  				fs_info->qgroup_rescan_progress.objectid);
bed92eae2   Arne Jansen   Btrfs: qgroup imp...
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
  
  	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;
06b3a860d   Wang Shilong   Btrfs: fix missin...
858
  	struct extent_buffer *leaf = NULL;
bed92eae2   Arne Jansen   Btrfs: qgroup imp...
859
  	int ret;
06b3a860d   Wang Shilong   Btrfs: fix missin...
860
  	int nr = 0;
bed92eae2   Arne Jansen   Btrfs: qgroup imp...
861

bed92eae2   Arne Jansen   Btrfs: qgroup imp...
862
863
864
  	path = btrfs_alloc_path();
  	if (!path)
  		return -ENOMEM;
06b3a860d   Wang Shilong   Btrfs: fix missin...
865
866
867
868
869
  	path->leave_spinning = 1;
  
  	key.objectid = 0;
  	key.offset = 0;
  	key.type = 0;
bed92eae2   Arne Jansen   Btrfs: qgroup imp...
870

06b3a860d   Wang Shilong   Btrfs: fix missin...
871
  	while (1) {
bed92eae2   Arne Jansen   Btrfs: qgroup imp...
872
  		ret = btrfs_search_slot(trans, root, &key, path, -1, 1);
06b3a860d   Wang Shilong   Btrfs: fix missin...
873
874
875
876
877
  		if (ret < 0)
  			goto out;
  		leaf = path->nodes[0];
  		nr = btrfs_header_nritems(leaf);
  		if (!nr)
bed92eae2   Arne Jansen   Btrfs: qgroup imp...
878
  			break;
06b3a860d   Wang Shilong   Btrfs: fix missin...
879
880
881
882
883
884
885
  		/*
  		 * 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);
bed92eae2   Arne Jansen   Btrfs: qgroup imp...
886
887
  		if (ret)
  			goto out;
06b3a860d   Wang Shilong   Btrfs: fix missin...
888

bed92eae2   Arne Jansen   Btrfs: qgroup imp...
889
890
891
892
  		btrfs_release_path(path);
  	}
  	ret = 0;
  out:
bed92eae2   Arne Jansen   Btrfs: qgroup imp...
893
894
895
  	btrfs_free_path(path);
  	return ret;
  }
340f1aa27   Nikolay Borisov   btrfs: qgroups: M...
896
  int btrfs_quota_enable(struct btrfs_fs_info *fs_info)
bed92eae2   Arne Jansen   Btrfs: qgroup imp...
897
898
  {
  	struct btrfs_root *quota_root;
7708f029d   Wang Shilong   Btrfs: creating t...
899
  	struct btrfs_root *tree_root = fs_info->tree_root;
bed92eae2   Arne Jansen   Btrfs: qgroup imp...
900
901
902
903
  	struct btrfs_path *path = NULL;
  	struct btrfs_qgroup_status_item *ptr;
  	struct extent_buffer *leaf;
  	struct btrfs_key key;
7708f029d   Wang Shilong   Btrfs: creating t...
904
905
  	struct btrfs_key found_key;
  	struct btrfs_qgroup *qgroup = NULL;
340f1aa27   Nikolay Borisov   btrfs: qgroups: M...
906
  	struct btrfs_trans_handle *trans = NULL;
bed92eae2   Arne Jansen   Btrfs: qgroup imp...
907
  	int ret = 0;
7708f029d   Wang Shilong   Btrfs: creating t...
908
  	int slot;
bed92eae2   Arne Jansen   Btrfs: qgroup imp...
909

f2f6ed3d5   Wang Shilong   Btrfs: introduce ...
910
  	mutex_lock(&fs_info->qgroup_ioctl_lock);
5d23515be   Nikolay Borisov   btrfs: Move qgrou...
911
  	if (fs_info->quota_root)
bed92eae2   Arne Jansen   Btrfs: qgroup imp...
912
  		goto out;
bed92eae2   Arne Jansen   Btrfs: qgroup imp...
913

7503b83d8   David Sterba   btrfs: move ulist...
914
915
916
917
918
  	fs_info->qgroup_ulist = ulist_alloc(GFP_KERNEL);
  	if (!fs_info->qgroup_ulist) {
  		ret = -ENOMEM;
  		goto out;
  	}
49e5fb462   Qu Wenruo   btrfs: qgroup: ex...
919
920
921
  	ret = btrfs_sysfs_add_qgroups(fs_info);
  	if (ret < 0)
  		goto out;
340f1aa27   Nikolay Borisov   btrfs: qgroups: M...
922
923
924
925
926
927
928
929
930
931
932
933
934
935
  	/*
  	 * 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;
  	}
bed92eae2   Arne Jansen   Btrfs: qgroup imp...
936
937
938
  	/*
  	 * initially create the quota tree
  	 */
9b7a2440a   David Sterba   btrfs: get fs_inf...
939
  	quota_root = btrfs_create_tree(trans, BTRFS_QUOTA_TREE_OBJECTID);
bed92eae2   Arne Jansen   Btrfs: qgroup imp...
940
941
  	if (IS_ERR(quota_root)) {
  		ret =  PTR_ERR(quota_root);
340f1aa27   Nikolay Borisov   btrfs: qgroups: M...
942
  		btrfs_abort_transaction(trans, ret);
bed92eae2   Arne Jansen   Btrfs: qgroup imp...
943
944
945
946
  		goto out;
  	}
  
  	path = btrfs_alloc_path();
5b7ff5b3c   Tsutomu Itoh   Btrfs: fix memory...
947
948
  	if (!path) {
  		ret = -ENOMEM;
340f1aa27   Nikolay Borisov   btrfs: qgroups: M...
949
  		btrfs_abort_transaction(trans, ret);
5b7ff5b3c   Tsutomu Itoh   Btrfs: fix memory...
950
951
  		goto out_free_root;
  	}
bed92eae2   Arne Jansen   Btrfs: qgroup imp...
952
953
954
955
956
957
958
  
  	key.objectid = 0;
  	key.type = BTRFS_QGROUP_STATUS_KEY;
  	key.offset = 0;
  
  	ret = btrfs_insert_empty_item(trans, quota_root, path, &key,
  				      sizeof(*ptr));
340f1aa27   Nikolay Borisov   btrfs: qgroups: M...
959
960
  	if (ret) {
  		btrfs_abort_transaction(trans, ret);
5b7ff5b3c   Tsutomu Itoh   Btrfs: fix memory...
961
  		goto out_free_path;
340f1aa27   Nikolay Borisov   btrfs: qgroups: M...
962
  	}
bed92eae2   Arne Jansen   Btrfs: qgroup imp...
963
964
965
966
967
968
969
970
971
  
  	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);
2f2320360   Jan Schmidt   Btrfs: rescan for...
972
  	btrfs_set_qgroup_status_rescan(leaf, ptr, 0);
bed92eae2   Arne Jansen   Btrfs: qgroup imp...
973
974
  
  	btrfs_mark_buffer_dirty(leaf);
7708f029d   Wang Shilong   Btrfs: creating t...
975
976
977
978
979
980
981
982
  	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;
340f1aa27   Nikolay Borisov   btrfs: qgroups: M...
983
984
  	if (ret < 0) {
  		btrfs_abort_transaction(trans, ret);
7708f029d   Wang Shilong   Btrfs: creating t...
985
  		goto out_free_path;
340f1aa27   Nikolay Borisov   btrfs: qgroups: M...
986
  	}
7708f029d   Wang Shilong   Btrfs: creating t...
987
988
989
990
991
992
993
994
995
  
  	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);
340f1aa27   Nikolay Borisov   btrfs: qgroups: M...
996
997
  			if (ret) {
  				btrfs_abort_transaction(trans, ret);
7708f029d   Wang Shilong   Btrfs: creating t...
998
  				goto out_free_path;
340f1aa27   Nikolay Borisov   btrfs: qgroups: M...
999
  			}
7708f029d   Wang Shilong   Btrfs: creating t...
1000

7708f029d   Wang Shilong   Btrfs: creating t...
1001
1002
  			qgroup = add_qgroup_rb(fs_info, found_key.offset);
  			if (IS_ERR(qgroup)) {
7708f029d   Wang Shilong   Btrfs: creating t...
1003
  				ret = PTR_ERR(qgroup);
340f1aa27   Nikolay Borisov   btrfs: qgroups: M...
1004
  				btrfs_abort_transaction(trans, ret);
7708f029d   Wang Shilong   Btrfs: creating t...
1005
1006
  				goto out_free_path;
  			}
49e5fb462   Qu Wenruo   btrfs: qgroup: ex...
1007
1008
1009
1010
1011
  			ret = btrfs_sysfs_add_one_qgroup(fs_info, qgroup);
  			if (ret < 0) {
  				btrfs_abort_transaction(trans, ret);
  				goto out_free_path;
  			}
7708f029d   Wang Shilong   Btrfs: creating t...
1012
1013
  		}
  		ret = btrfs_next_item(tree_root, path);
340f1aa27   Nikolay Borisov   btrfs: qgroups: M...
1014
1015
  		if (ret < 0) {
  			btrfs_abort_transaction(trans, ret);
7708f029d   Wang Shilong   Btrfs: creating t...
1016
  			goto out_free_path;
340f1aa27   Nikolay Borisov   btrfs: qgroups: M...
1017
  		}
7708f029d   Wang Shilong   Btrfs: creating t...
1018
1019
1020
1021
1022
1023
1024
  		if (ret)
  			break;
  	}
  
  out_add_root:
  	btrfs_release_path(path);
  	ret = add_qgroup_item(trans, quota_root, BTRFS_FS_TREE_OBJECTID);
340f1aa27   Nikolay Borisov   btrfs: qgroups: M...
1025
1026
  	if (ret) {
  		btrfs_abort_transaction(trans, ret);
7708f029d   Wang Shilong   Btrfs: creating t...
1027
  		goto out_free_path;
340f1aa27   Nikolay Borisov   btrfs: qgroups: M...
1028
  	}
7708f029d   Wang Shilong   Btrfs: creating t...
1029

7708f029d   Wang Shilong   Btrfs: creating t...
1030
1031
  	qgroup = add_qgroup_rb(fs_info, BTRFS_FS_TREE_OBJECTID);
  	if (IS_ERR(qgroup)) {
7708f029d   Wang Shilong   Btrfs: creating t...
1032
  		ret = PTR_ERR(qgroup);
340f1aa27   Nikolay Borisov   btrfs: qgroups: M...
1033
  		btrfs_abort_transaction(trans, ret);
7708f029d   Wang Shilong   Btrfs: creating t...
1034
1035
  		goto out_free_path;
  	}
49e5fb462   Qu Wenruo   btrfs: qgroup: ex...
1036
1037
1038
1039
1040
  	ret = btrfs_sysfs_add_one_qgroup(fs_info, qgroup);
  	if (ret < 0) {
  		btrfs_abort_transaction(trans, ret);
  		goto out_free_path;
  	}
340f1aa27   Nikolay Borisov   btrfs: qgroups: M...
1041
1042
  
  	ret = btrfs_commit_transaction(trans);
b9b8a41ad   Dan Carpenter   btrfs: use after ...
1043
1044
  	trans = NULL;
  	if (ret)
340f1aa27   Nikolay Borisov   btrfs: qgroups: M...
1045
  		goto out_free_path;
340f1aa27   Nikolay Borisov   btrfs: qgroups: M...
1046

9a6f209e3   Filipe Manana   Btrfs: fix deadlo...
1047
1048
1049
1050
1051
1052
1053
1054
1055
  	/*
  	 * 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);
5d23515be   Nikolay Borisov   btrfs: Move qgrou...
1056
1057
1058
  	ret = qgroup_rescan_init(fs_info, 0, 1);
  	if (!ret) {
  	        qgroup_rescan_zero_tracking(fs_info);
d61acbbf5   Qu Wenruo   btrfs: qgroup: en...
1059
  		fs_info->qgroup_rescan_running = true;
5d23515be   Nikolay Borisov   btrfs: Move qgrou...
1060
1061
1062
  	        btrfs_queue_work(fs_info->qgroup_rescan_workers,
  	                         &fs_info->qgroup_rescan_work);
  	}
5b7ff5b3c   Tsutomu Itoh   Btrfs: fix memory...
1063
  out_free_path:
bed92eae2   Arne Jansen   Btrfs: qgroup imp...
1064
  	btrfs_free_path(path);
5b7ff5b3c   Tsutomu Itoh   Btrfs: fix memory...
1065
  out_free_root:
8c38938c7   Josef Bacik   btrfs: move the r...
1066
  	if (ret)
002465289   Josef Bacik   btrfs: rename btr...
1067
  		btrfs_put_root(quota_root);
5b7ff5b3c   Tsutomu Itoh   Btrfs: fix memory...
1068
  out:
eb1716af8   Jan Schmidt   Btrfs: avoid doub...
1069
  	if (ret) {
1e8f91586   Wang Shilong   Btrfs: introduce ...
1070
  		ulist_free(fs_info->qgroup_ulist);
eb1716af8   Jan Schmidt   Btrfs: avoid doub...
1071
  		fs_info->qgroup_ulist = NULL;
340f1aa27   Nikolay Borisov   btrfs: qgroups: M...
1072
1073
  		if (trans)
  			btrfs_end_transaction(trans);
49e5fb462   Qu Wenruo   btrfs: qgroup: ex...
1074
  		btrfs_sysfs_del_qgroups(fs_info);
eb1716af8   Jan Schmidt   Btrfs: avoid doub...
1075
  	}
f2f6ed3d5   Wang Shilong   Btrfs: introduce ...
1076
  	mutex_unlock(&fs_info->qgroup_ioctl_lock);
bed92eae2   Arne Jansen   Btrfs: qgroup imp...
1077
1078
  	return ret;
  }
340f1aa27   Nikolay Borisov   btrfs: qgroups: M...
1079
  int btrfs_quota_disable(struct btrfs_fs_info *fs_info)
bed92eae2   Arne Jansen   Btrfs: qgroup imp...
1080
  {
bed92eae2   Arne Jansen   Btrfs: qgroup imp...
1081
  	struct btrfs_root *quota_root;
340f1aa27   Nikolay Borisov   btrfs: qgroups: M...
1082
  	struct btrfs_trans_handle *trans = NULL;
bed92eae2   Arne Jansen   Btrfs: qgroup imp...
1083
  	int ret = 0;
f2f6ed3d5   Wang Shilong   Btrfs: introduce ...
1084
  	mutex_lock(&fs_info->qgroup_ioctl_lock);
58400fce5   Wang Shilong   Btrfs: remove som...
1085
  	if (!fs_info->quota_root)
f2f6ed3d5   Wang Shilong   Btrfs: introduce ...
1086
  		goto out;
340f1aa27   Nikolay Borisov   btrfs: qgroups: M...
1087
1088
1089
1090
1091
1092
1093
1094
1095
1096
1097
1098
  
  	/*
  	 * 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;
  	}
afcdd129e   Josef Bacik   Btrfs: add a flag...
1099
  	clear_bit(BTRFS_FS_QUOTA_ENABLED, &fs_info->flags);
d06f23d6a   Jeff Mahoney   btrfs: waiting on...
1100
  	btrfs_qgroup_wait_for_completion(fs_info, false);
967ef5131   Justin Maggard   btrfs: qgroup: fi...
1101
  	spin_lock(&fs_info->qgroup_lock);
bed92eae2   Arne Jansen   Btrfs: qgroup imp...
1102
1103
  	quota_root = fs_info->quota_root;
  	fs_info->quota_root = NULL;
8ea0ec9e0   Dongsheng Yang   btrfs: qgroup: cl...
1104
  	fs_info->qgroup_flags &= ~BTRFS_QGROUP_STATUS_FLAG_ON;
bed92eae2   Arne Jansen   Btrfs: qgroup imp...
1105
  	spin_unlock(&fs_info->qgroup_lock);
e685da14a   Wang Shilong   Btrfs: move btrfs...
1106
  	btrfs_free_qgroup_config(fs_info);
bed92eae2   Arne Jansen   Btrfs: qgroup imp...
1107
  	ret = btrfs_clean_quota_tree(trans, quota_root);
340f1aa27   Nikolay Borisov   btrfs: qgroups: M...
1108
1109
1110
1111
  	if (ret) {
  		btrfs_abort_transaction(trans, ret);
  		goto end_trans;
  	}
bed92eae2   Arne Jansen   Btrfs: qgroup imp...
1112

ab9ce7d42   Lu Fengqi   btrfs: Remove fs_...
1113
  	ret = btrfs_del_root(trans, &quota_root->root_key);
340f1aa27   Nikolay Borisov   btrfs: qgroups: M...
1114
1115
1116
1117
  	if (ret) {
  		btrfs_abort_transaction(trans, ret);
  		goto end_trans;
  	}
bed92eae2   Arne Jansen   Btrfs: qgroup imp...
1118
1119
1120
1121
  
  	list_del(&quota_root->dirty_list);
  
  	btrfs_tree_lock(quota_root->node);
6a884d7d5   David Sterba   btrfs: get fs_inf...
1122
  	btrfs_clean_tree_block(quota_root->node);
bed92eae2   Arne Jansen   Btrfs: qgroup imp...
1123
1124
  	btrfs_tree_unlock(quota_root->node);
  	btrfs_free_tree_block(trans, quota_root, quota_root->node, 0, 1);
002465289   Josef Bacik   btrfs: rename btr...
1125
  	btrfs_put_root(quota_root);
340f1aa27   Nikolay Borisov   btrfs: qgroups: M...
1126
1127
1128
  
  end_trans:
  	ret = btrfs_end_transaction(trans);
bed92eae2   Arne Jansen   Btrfs: qgroup imp...
1129
  out:
f2f6ed3d5   Wang Shilong   Btrfs: introduce ...
1130
  	mutex_unlock(&fs_info->qgroup_ioctl_lock);
bed92eae2   Arne Jansen   Btrfs: qgroup imp...
1131
1132
  	return ret;
  }
2f2320360   Jan Schmidt   Btrfs: rescan for...
1133
1134
  static void qgroup_dirty(struct btrfs_fs_info *fs_info,
  			 struct btrfs_qgroup *qgroup)
bed92eae2   Arne Jansen   Btrfs: qgroup imp...
1135
  {
2f2320360   Jan Schmidt   Btrfs: rescan for...
1136
1137
  	if (list_empty(&qgroup->dirty))
  		list_add(&qgroup->dirty, &fs_info->dirty_qgroups);
bed92eae2   Arne Jansen   Btrfs: qgroup imp...
1138
  }
9c8b35b1b   Qu Wenruo   btrfs: quota: Aut...
1139
  /*
429d6275d   Qu Wenruo   btrfs: qgroup: Fi...
1140
1141
1142
   * The easy accounting, we're updating qgroup relationship whose child qgroup
   * only has exclusive extents.
   *
52042d8e8   Andrea Gelmini   btrfs: Fix typos ...
1143
   * In this case, all exclusive extents will also be exclusive for parent, so
429d6275d   Qu Wenruo   btrfs: qgroup: Fi...
1144
1145
1146
1147
1148
1149
   * 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).
9c8b35b1b   Qu Wenruo   btrfs: quota: Aut...
1150
1151
1152
1153
1154
   *
   * Caller should hold fs_info->qgroup_lock.
   */
  static int __qgroup_excl_accounting(struct btrfs_fs_info *fs_info,
  				    struct ulist *tmp, u64 ref_root,
429d6275d   Qu Wenruo   btrfs: qgroup: Fi...
1155
  				    struct btrfs_qgroup *src, int sign)
9c8b35b1b   Qu Wenruo   btrfs: quota: Aut...
1156
1157
1158
1159
1160
  {
  	struct btrfs_qgroup *qgroup;
  	struct btrfs_qgroup_list *glist;
  	struct ulist_node *unode;
  	struct ulist_iterator uiter;
429d6275d   Qu Wenruo   btrfs: qgroup: Fi...
1161
  	u64 num_bytes = src->excl;
9c8b35b1b   Qu Wenruo   btrfs: quota: Aut...
1162
1163
1164
1165
1166
1167
1168
1169
1170
1171
1172
1173
  	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;
429d6275d   Qu Wenruo   btrfs: qgroup: Fi...
1174
1175
  
  	if (sign > 0)
64ee4e751   Qu Wenruo   btrfs: qgroup: Up...
1176
  		qgroup_rsv_add_by_qgroup(fs_info, qgroup, src);
429d6275d   Qu Wenruo   btrfs: qgroup: Fi...
1177
  	else
64ee4e751   Qu Wenruo   btrfs: qgroup: Up...
1178
  		qgroup_rsv_release_by_qgroup(fs_info, qgroup, src);
9c8b35b1b   Qu Wenruo   btrfs: quota: Aut...
1179
1180
1181
1182
1183
1184
  
  	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,
ef2fff64f   David Sterba   btrfs: rename hel...
1185
  				qgroup_to_aux(glist->group), GFP_ATOMIC);
9c8b35b1b   Qu Wenruo   btrfs: quota: Aut...
1186
1187
1188
1189
1190
1191
1192
  		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))) {
ef2fff64f   David Sterba   btrfs: rename hel...
1193
  		qgroup = unode_aux_to_qgroup(unode);
9c8b35b1b   Qu Wenruo   btrfs: quota: Aut...
1194
1195
1196
1197
  		qgroup->rfer += sign * num_bytes;
  		qgroup->rfer_cmpr += sign * num_bytes;
  		WARN_ON(sign < 0 && qgroup->excl < num_bytes);
  		qgroup->excl += sign * num_bytes;
429d6275d   Qu Wenruo   btrfs: qgroup: Fi...
1198
  		if (sign > 0)
64ee4e751   Qu Wenruo   btrfs: qgroup: Up...
1199
  			qgroup_rsv_add_by_qgroup(fs_info, qgroup, src);
429d6275d   Qu Wenruo   btrfs: qgroup: Fi...
1200
  		else
64ee4e751   Qu Wenruo   btrfs: qgroup: Up...
1201
  			qgroup_rsv_release_by_qgroup(fs_info, qgroup, src);
9c8b35b1b   Qu Wenruo   btrfs: quota: Aut...
1202
1203
1204
1205
1206
1207
  		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,
ef2fff64f   David Sterba   btrfs: rename hel...
1208
  					qgroup_to_aux(glist->group), GFP_ATOMIC);
9c8b35b1b   Qu Wenruo   btrfs: quota: Aut...
1209
1210
1211
1212
1213
1214
1215
1216
1217
1218
1219
1220
1221
1222
1223
1224
1225
1226
1227
1228
1229
1230
1231
1232
1233
1234
1235
1236
1237
1238
1239
1240
1241
1242
1243
  			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,
429d6275d   Qu Wenruo   btrfs: qgroup: Fi...
1244
  					       qgroup, sign);
9c8b35b1b   Qu Wenruo   btrfs: quota: Aut...
1245
1246
1247
1248
1249
1250
1251
1252
1253
1254
  		if (err < 0) {
  			ret = err;
  			goto out;
  		}
  	}
  out:
  	if (ret)
  		fs_info->qgroup_flags |= BTRFS_QGROUP_STATUS_FLAG_INCONSISTENT;
  	return ret;
  }
9f8a6ce6b   Lu Fengqi   btrfs: qgroup: Dr...
1255
1256
  int btrfs_add_qgroup_relation(struct btrfs_trans_handle *trans, u64 src,
  			      u64 dst)
bed92eae2   Arne Jansen   Btrfs: qgroup imp...
1257
  {
9f8a6ce6b   Lu Fengqi   btrfs: qgroup: Dr...
1258
  	struct btrfs_fs_info *fs_info = trans->fs_info;
b7fef4f59   Wang Shilong   Btrfs: fix missin...
1259
1260
  	struct btrfs_qgroup *parent;
  	struct btrfs_qgroup *member;
534e6623b   Wang Shilong   Btrfs: add all io...
1261
  	struct btrfs_qgroup_list *list;
9c8b35b1b   Qu Wenruo   btrfs: quota: Aut...
1262
  	struct ulist *tmp;
bed92eae2   Arne Jansen   Btrfs: qgroup imp...
1263
  	int ret = 0;
8465ecec9   Qu Wenruo   btrfs: Check qgro...
1264
1265
1266
  	/* Check the level of src and dst first */
  	if (btrfs_qgroup_level(src) >= btrfs_qgroup_level(dst))
  		return -EINVAL;
6602caf14   David Sterba   btrfs: use GFP_KE...
1267
  	tmp = ulist_alloc(GFP_KERNEL);
ab3680dd1   Christian Engelmayer   btrfs: qgroup: Fi...
1268
1269
  	if (!tmp)
  		return -ENOMEM;
f2f6ed3d5   Wang Shilong   Btrfs: introduce ...
1270
  	mutex_lock(&fs_info->qgroup_ioctl_lock);
e3b0edd29   Marcos Paulo de Souza   btrfs: qgroup: re...
1271
  	if (!fs_info->quota_root) {
8a36e408d   Marcos Paulo de Souza   btrfs: qgroup: re...
1272
  		ret = -ENOTCONN;
f2f6ed3d5   Wang Shilong   Btrfs: introduce ...
1273
1274
  		goto out;
  	}
b7fef4f59   Wang Shilong   Btrfs: fix missin...
1275
1276
1277
1278
1279
1280
  	member = find_qgroup_rb(fs_info, src);
  	parent = find_qgroup_rb(fs_info, dst);
  	if (!member || !parent) {
  		ret = -EINVAL;
  		goto out;
  	}
bed92eae2   Arne Jansen   Btrfs: qgroup imp...
1281

534e6623b   Wang Shilong   Btrfs: add all io...
1282
1283
1284
1285
1286
1287
1288
  	/* check if such qgroup relation exist firstly */
  	list_for_each_entry(list, &member->groups, next_group) {
  		if (list->group == parent) {
  			ret = -EEXIST;
  			goto out;
  		}
  	}
711169c40   Lu Fengqi   btrfs: qgroup: Dr...
1289
  	ret = add_qgroup_relation_item(trans, src, dst);
bed92eae2   Arne Jansen   Btrfs: qgroup imp...
1290
  	if (ret)
f2f6ed3d5   Wang Shilong   Btrfs: introduce ...
1291
  		goto out;
bed92eae2   Arne Jansen   Btrfs: qgroup imp...
1292

711169c40   Lu Fengqi   btrfs: qgroup: Dr...
1293
  	ret = add_qgroup_relation_item(trans, dst, src);
bed92eae2   Arne Jansen   Btrfs: qgroup imp...
1294
  	if (ret) {
99d7f09ac   Lu Fengqi   btrfs: qgroup: Dr...
1295
  		del_qgroup_relation_item(trans, src, dst);
f2f6ed3d5   Wang Shilong   Btrfs: introduce ...
1296
  		goto out;
bed92eae2   Arne Jansen   Btrfs: qgroup imp...
1297
1298
1299
  	}
  
  	spin_lock(&fs_info->qgroup_lock);
0b246afa6   Jeff Mahoney   btrfs: root->fs_i...
1300
  	ret = add_relation_rb(fs_info, src, dst);
9c8b35b1b   Qu Wenruo   btrfs: quota: Aut...
1301
1302
1303
1304
1305
  	if (ret < 0) {
  		spin_unlock(&fs_info->qgroup_lock);
  		goto out;
  	}
  	ret = quick_update_accounting(fs_info, tmp, src, dst, 1);
bed92eae2   Arne Jansen   Btrfs: qgroup imp...
1306
  	spin_unlock(&fs_info->qgroup_lock);
f2f6ed3d5   Wang Shilong   Btrfs: introduce ...
1307
1308
  out:
  	mutex_unlock(&fs_info->qgroup_ioctl_lock);
9c8b35b1b   Qu Wenruo   btrfs: quota: Aut...
1309
  	ulist_free(tmp);
bed92eae2   Arne Jansen   Btrfs: qgroup imp...
1310
1311
  	return ret;
  }
6b36f1aa5   Lu Fengqi   btrfs: qgroup: Dr...
1312
1313
  static int __del_qgroup_relation(struct btrfs_trans_handle *trans, u64 src,
  				 u64 dst)
bed92eae2   Arne Jansen   Btrfs: qgroup imp...
1314
  {
6b36f1aa5   Lu Fengqi   btrfs: qgroup: Dr...
1315
  	struct btrfs_fs_info *fs_info = trans->fs_info;
534e6623b   Wang Shilong   Btrfs: add all io...
1316
1317
1318
  	struct btrfs_qgroup *parent;
  	struct btrfs_qgroup *member;
  	struct btrfs_qgroup_list *list;
9c8b35b1b   Qu Wenruo   btrfs: quota: Aut...
1319
  	struct ulist *tmp;
73798c465   Qu Wenruo   btrfs: qgroup: Tr...
1320
  	bool found = false;
bed92eae2   Arne Jansen   Btrfs: qgroup imp...
1321
  	int ret = 0;
73798c465   Qu Wenruo   btrfs: qgroup: Tr...
1322
  	int ret2;
bed92eae2   Arne Jansen   Btrfs: qgroup imp...
1323

6602caf14   David Sterba   btrfs: use GFP_KE...
1324
  	tmp = ulist_alloc(GFP_KERNEL);
9c8b35b1b   Qu Wenruo   btrfs: quota: Aut...
1325
1326
  	if (!tmp)
  		return -ENOMEM;
e3b0edd29   Marcos Paulo de Souza   btrfs: qgroup: re...
1327
  	if (!fs_info->quota_root) {
8a36e408d   Marcos Paulo de Souza   btrfs: qgroup: re...
1328
  		ret = -ENOTCONN;
f2f6ed3d5   Wang Shilong   Btrfs: introduce ...
1329
1330
  		goto out;
  	}
bed92eae2   Arne Jansen   Btrfs: qgroup imp...
1331

534e6623b   Wang Shilong   Btrfs: add all io...
1332
1333
  	member = find_qgroup_rb(fs_info, src);
  	parent = find_qgroup_rb(fs_info, dst);
73798c465   Qu Wenruo   btrfs: qgroup: Tr...
1334
1335
1336
1337
1338
1339
  	/*
  	 * The parent/member pair doesn't exist, then try to delete the dead
  	 * relation items only.
  	 */
  	if (!member || !parent)
  		goto delete_item;
534e6623b   Wang Shilong   Btrfs: add all io...
1340
1341
1342
  
  	/* check if such qgroup relation exist firstly */
  	list_for_each_entry(list, &member->groups, next_group) {
73798c465   Qu Wenruo   btrfs: qgroup: Tr...
1343
1344
1345
1346
  		if (list->group == parent) {
  			found = true;
  			break;
  		}
534e6623b   Wang Shilong   Btrfs: add all io...
1347
  	}
73798c465   Qu Wenruo   btrfs: qgroup: Tr...
1348
1349
  
  delete_item:
99d7f09ac   Lu Fengqi   btrfs: qgroup: Dr...
1350
  	ret = del_qgroup_relation_item(trans, src, dst);
73798c465   Qu Wenruo   btrfs: qgroup: Tr...
1351
1352
1353
1354
1355
  	if (ret < 0 && ret != -ENOENT)
  		goto out;
  	ret2 = del_qgroup_relation_item(trans, dst, src);
  	if (ret2 < 0 && ret2 != -ENOENT)
  		goto out;
bed92eae2   Arne Jansen   Btrfs: qgroup imp...
1356

73798c465   Qu Wenruo   btrfs: qgroup: Tr...
1357
1358
1359
1360
1361
1362
1363
1364
1365
1366
  	/* 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);
  	}
f2f6ed3d5   Wang Shilong   Btrfs: introduce ...
1367
  out:
9c8b35b1b   Qu Wenruo   btrfs: quota: Aut...
1368
  	ulist_free(tmp);
f5a6b1c53   Dongsheng Yang   btrfs: qgroup: al...
1369
1370
  	return ret;
  }
39616c273   Lu Fengqi   btrfs: qgroup: Dr...
1371
1372
  int btrfs_del_qgroup_relation(struct btrfs_trans_handle *trans, u64 src,
  			      u64 dst)
f5a6b1c53   Dongsheng Yang   btrfs: qgroup: al...
1373
  {
39616c273   Lu Fengqi   btrfs: qgroup: Dr...
1374
  	struct btrfs_fs_info *fs_info = trans->fs_info;
f5a6b1c53   Dongsheng Yang   btrfs: qgroup: al...
1375
1376
1377
  	int ret = 0;
  
  	mutex_lock(&fs_info->qgroup_ioctl_lock);
6b36f1aa5   Lu Fengqi   btrfs: qgroup: Dr...
1378
  	ret = __del_qgroup_relation(trans, src, dst);
f2f6ed3d5   Wang Shilong   Btrfs: introduce ...
1379
  	mutex_unlock(&fs_info->qgroup_ioctl_lock);
f5a6b1c53   Dongsheng Yang   btrfs: qgroup: al...
1380

bed92eae2   Arne Jansen   Btrfs: qgroup imp...
1381
1382
  	return ret;
  }
49a05ecde   Lu Fengqi   btrfs: qgroup: Dr...
1383
  int btrfs_create_qgroup(struct btrfs_trans_handle *trans, u64 qgroupid)
bed92eae2   Arne Jansen   Btrfs: qgroup imp...
1384
  {
49a05ecde   Lu Fengqi   btrfs: qgroup: Dr...
1385
  	struct btrfs_fs_info *fs_info = trans->fs_info;
bed92eae2   Arne Jansen   Btrfs: qgroup imp...
1386
1387
1388
  	struct btrfs_root *quota_root;
  	struct btrfs_qgroup *qgroup;
  	int ret = 0;
f2f6ed3d5   Wang Shilong   Btrfs: introduce ...
1389
  	mutex_lock(&fs_info->qgroup_ioctl_lock);
e3b0edd29   Marcos Paulo de Souza   btrfs: qgroup: re...
1390
  	if (!fs_info->quota_root) {
8a36e408d   Marcos Paulo de Souza   btrfs: qgroup: re...
1391
  		ret = -ENOTCONN;
f2f6ed3d5   Wang Shilong   Btrfs: introduce ...
1392
1393
  		goto out;
  	}
e3b0edd29   Marcos Paulo de Souza   btrfs: qgroup: re...
1394
  	quota_root = fs_info->quota_root;
534e6623b   Wang Shilong   Btrfs: add all io...
1395
1396
1397
1398
1399
  	qgroup = find_qgroup_rb(fs_info, qgroupid);
  	if (qgroup) {
  		ret = -EEXIST;
  		goto out;
  	}
bed92eae2   Arne Jansen   Btrfs: qgroup imp...
1400
1401
  
  	ret = add_qgroup_item(trans, quota_root, qgroupid);
534e6623b   Wang Shilong   Btrfs: add all io...
1402
1403
  	if (ret)
  		goto out;
bed92eae2   Arne Jansen   Btrfs: qgroup imp...
1404
1405
1406
1407
  
  	spin_lock(&fs_info->qgroup_lock);
  	qgroup = add_qgroup_rb(fs_info, qgroupid);
  	spin_unlock(&fs_info->qgroup_lock);
49e5fb462   Qu Wenruo   btrfs: qgroup: ex...
1408
  	if (IS_ERR(qgroup)) {
bed92eae2   Arne Jansen   Btrfs: qgroup imp...
1409
  		ret = PTR_ERR(qgroup);
49e5fb462   Qu Wenruo   btrfs: qgroup: ex...
1410
1411
1412
  		goto out;
  	}
  	ret = btrfs_sysfs_add_one_qgroup(fs_info, qgroup);
f2f6ed3d5   Wang Shilong   Btrfs: introduce ...
1413
1414
  out:
  	mutex_unlock(&fs_info->qgroup_ioctl_lock);
bed92eae2   Arne Jansen   Btrfs: qgroup imp...
1415
1416
  	return ret;
  }
3efbee1d0   Lu Fengqi   btrfs: qgroup: Dr...
1417
  int btrfs_remove_qgroup(struct btrfs_trans_handle *trans, u64 qgroupid)
bed92eae2   Arne Jansen   Btrfs: qgroup imp...
1418
  {
3efbee1d0   Lu Fengqi   btrfs: qgroup: Dr...
1419
  	struct btrfs_fs_info *fs_info = trans->fs_info;
2cf687039   Arne Jansen   Btrfs: prevent qg...
1420
  	struct btrfs_qgroup *qgroup;
f5a6b1c53   Dongsheng Yang   btrfs: qgroup: al...
1421
  	struct btrfs_qgroup_list *list;
bed92eae2   Arne Jansen   Btrfs: qgroup imp...
1422
  	int ret = 0;
f2f6ed3d5   Wang Shilong   Btrfs: introduce ...
1423
  	mutex_lock(&fs_info->qgroup_ioctl_lock);
e3b0edd29   Marcos Paulo de Souza   btrfs: qgroup: re...
1424
  	if (!fs_info->quota_root) {
8a36e408d   Marcos Paulo de Souza   btrfs: qgroup: re...
1425
  		ret = -ENOTCONN;
f2f6ed3d5   Wang Shilong   Btrfs: introduce ...
1426
1427
  		goto out;
  	}
bed92eae2   Arne Jansen   Btrfs: qgroup imp...
1428

2cf687039   Arne Jansen   Btrfs: prevent qg...
1429
  	qgroup = find_qgroup_rb(fs_info, qgroupid);
534e6623b   Wang Shilong   Btrfs: add all io...
1430
1431
1432
  	if (!qgroup) {
  		ret = -ENOENT;
  		goto out;
2cf687039   Arne Jansen   Btrfs: prevent qg...
1433
  	}
b90e22ba4   Lu Fengqi   btrfs: qgroup: mo...
1434
1435
1436
1437
1438
1439
  
  	/* Check if there are no children of this qgroup */
  	if (!list_empty(&qgroup->members)) {
  		ret = -EBUSY;
  		goto out;
  	}
69104618f   Lu Fengqi   btrfs: qgroup: Dr...
1440
  	ret = del_qgroup_item(trans, qgroupid);
36b96fdc6   Sargun Dhillon   btrfs: Report err...
1441
1442
  	if (ret && ret != -ENOENT)
  		goto out;
bed92eae2   Arne Jansen   Btrfs: qgroup imp...
1443

f5a6b1c53   Dongsheng Yang   btrfs: qgroup: al...
1444
1445
1446
  	while (!list_empty(&qgroup->groups)) {
  		list = list_first_entry(&qgroup->groups,
  					struct btrfs_qgroup_list, next_group);
6b36f1aa5   Lu Fengqi   btrfs: qgroup: Dr...
1447
1448
  		ret = __del_qgroup_relation(trans, qgroupid,
  					    list->group->qgroupid);
f5a6b1c53   Dongsheng Yang   btrfs: qgroup: al...
1449
1450
1451
  		if (ret)
  			goto out;
  	}
bed92eae2   Arne Jansen   Btrfs: qgroup imp...
1452
  	spin_lock(&fs_info->qgroup_lock);
0b246afa6   Jeff Mahoney   btrfs: root->fs_i...
1453
  	del_qgroup_rb(fs_info, qgroupid);
bed92eae2   Arne Jansen   Btrfs: qgroup imp...
1454
  	spin_unlock(&fs_info->qgroup_lock);
f2f6ed3d5   Wang Shilong   Btrfs: introduce ...
1455
1456
  out:
  	mutex_unlock(&fs_info->qgroup_ioctl_lock);
bed92eae2   Arne Jansen   Btrfs: qgroup imp...
1457
1458
  	return ret;
  }
f0042d5e9   Lu Fengqi   btrfs: qgroup: Dr...
1459
  int btrfs_limit_qgroup(struct btrfs_trans_handle *trans, u64 qgroupid,
bed92eae2   Arne Jansen   Btrfs: qgroup imp...
1460
1461
  		       struct btrfs_qgroup_limit *limit)
  {
f0042d5e9   Lu Fengqi   btrfs: qgroup: Dr...
1462
  	struct btrfs_fs_info *fs_info = trans->fs_info;
bed92eae2   Arne Jansen   Btrfs: qgroup imp...
1463
1464
  	struct btrfs_qgroup *qgroup;
  	int ret = 0;
fe7599079   Yang Dongsheng   btrfs: qgroup: al...
1465
1466
1467
1468
1469
  	/* Sometimes we would want to clear the limit on this qgroup.
  	 * To meet this requirement, we treat the -1 as a special value
  	 * which tell kernel to clear the limit on this qgroup.
  	 */
  	const u64 CLEAR_VALUE = -1;
bed92eae2   Arne Jansen   Btrfs: qgroup imp...
1470

f2f6ed3d5   Wang Shilong   Btrfs: introduce ...
1471
  	mutex_lock(&fs_info->qgroup_ioctl_lock);
e3b0edd29   Marcos Paulo de Souza   btrfs: qgroup: re...
1472
  	if (!fs_info->quota_root) {
8a36e408d   Marcos Paulo de Souza   btrfs: qgroup: re...
1473
  		ret = -ENOTCONN;
f2f6ed3d5   Wang Shilong   Btrfs: introduce ...
1474
1475
  		goto out;
  	}
bed92eae2   Arne Jansen   Btrfs: qgroup imp...
1476

ddb47afa5   Wang Shilong   Btrfs: fix a warn...
1477
1478
1479
1480
1481
  	qgroup = find_qgroup_rb(fs_info, qgroupid);
  	if (!qgroup) {
  		ret = -ENOENT;
  		goto out;
  	}
bed92eae2   Arne Jansen   Btrfs: qgroup imp...
1482

58400fce5   Wang Shilong   Btrfs: remove som...
1483
  	spin_lock(&fs_info->qgroup_lock);
fe7599079   Yang Dongsheng   btrfs: qgroup: al...
1484
1485
1486
1487
1488
1489
1490
1491
1492
1493
1494
1495
1496
1497
1498
1499
1500
1501
1502
1503
1504
1505
1506
1507
1508
1509
1510
1511
1512
1513
1514
1515
1516
1517
1518
1519
  	if (limit->flags & BTRFS_QGROUP_LIMIT_MAX_RFER) {
  		if (limit->max_rfer == CLEAR_VALUE) {
  			qgroup->lim_flags &= ~BTRFS_QGROUP_LIMIT_MAX_RFER;
  			limit->flags &= ~BTRFS_QGROUP_LIMIT_MAX_RFER;
  			qgroup->max_rfer = 0;
  		} else {
  			qgroup->max_rfer = limit->max_rfer;
  		}
  	}
  	if (limit->flags & BTRFS_QGROUP_LIMIT_MAX_EXCL) {
  		if (limit->max_excl == CLEAR_VALUE) {
  			qgroup->lim_flags &= ~BTRFS_QGROUP_LIMIT_MAX_EXCL;
  			limit->flags &= ~BTRFS_QGROUP_LIMIT_MAX_EXCL;
  			qgroup->max_excl = 0;
  		} else {
  			qgroup->max_excl = limit->max_excl;
  		}
  	}
  	if (limit->flags & BTRFS_QGROUP_LIMIT_RSV_RFER) {
  		if (limit->rsv_rfer == CLEAR_VALUE) {
  			qgroup->lim_flags &= ~BTRFS_QGROUP_LIMIT_RSV_RFER;
  			limit->flags &= ~BTRFS_QGROUP_LIMIT_RSV_RFER;
  			qgroup->rsv_rfer = 0;
  		} else {
  			qgroup->rsv_rfer = limit->rsv_rfer;
  		}
  	}
  	if (limit->flags & BTRFS_QGROUP_LIMIT_RSV_EXCL) {
  		if (limit->rsv_excl == CLEAR_VALUE) {
  			qgroup->lim_flags &= ~BTRFS_QGROUP_LIMIT_RSV_EXCL;
  			limit->flags &= ~BTRFS_QGROUP_LIMIT_RSV_EXCL;
  			qgroup->rsv_excl = 0;
  		} else {
  			qgroup->rsv_excl = limit->rsv_excl;
  		}
  	}
03477d945   Dongsheng Yang   btrfs: qgroup: fi...
1520
  	qgroup->lim_flags |= limit->flags;
bed92eae2   Arne Jansen   Btrfs: qgroup imp...
1521
  	spin_unlock(&fs_info->qgroup_lock);
1510e71c6   Dongsheng Yang   btrfs: qgroup: co...
1522

ac8a866af   Lu Fengqi   btrfs: qgroup: Dr...
1523
  	ret = update_qgroup_limit_item(trans, qgroup);
1510e71c6   Dongsheng Yang   btrfs: qgroup: co...
1524
1525
1526
1527
1528
  	if (ret) {
  		fs_info->qgroup_flags |= BTRFS_QGROUP_STATUS_FLAG_INCONSISTENT;
  		btrfs_info(fs_info, "unable to update quota limit for %llu",
  		       qgroupid);
  	}
f2f6ed3d5   Wang Shilong   Btrfs: introduce ...
1529
1530
  out:
  	mutex_unlock(&fs_info->qgroup_ioctl_lock);
bed92eae2   Arne Jansen   Btrfs: qgroup imp...
1531
1532
  	return ret;
  }
1152651a0   Mark Fasheh   btrfs: qgroup: ac...
1533

50b3e040b   Qu Wenruo   btrfs: qgroup: Re...
1534
  int btrfs_qgroup_trace_extent_nolock(struct btrfs_fs_info *fs_info,
cb93b52cc   Qu Wenruo   btrfs: qgroup: Re...
1535
1536
  				struct btrfs_delayed_ref_root *delayed_refs,
  				struct btrfs_qgroup_extent_record *record)
3368d001b   Qu Wenruo   btrfs: qgroup: Re...
1537
1538
1539
1540
1541
  {
  	struct rb_node **p = &delayed_refs->dirty_extent_root.rb_node;
  	struct rb_node *parent_node = NULL;
  	struct btrfs_qgroup_extent_record *entry;
  	u64 bytenr = record->bytenr;
a4666e688   David Sterba   btrfs: use lockde...
1542
  	lockdep_assert_held(&delayed_refs->lock);
50b3e040b   Qu Wenruo   btrfs: qgroup: Re...
1543
  	trace_btrfs_qgroup_trace_extent(fs_info, record);
82bd101b5   Mark Fasheh   btrfs: qgroup: ac...
1544

3368d001b   Qu Wenruo   btrfs: qgroup: Re...
1545
1546
1547
1548
  	while (*p) {
  		parent_node = *p;
  		entry = rb_entry(parent_node, struct btrfs_qgroup_extent_record,
  				 node);
1418bae1c   Qu Wenruo   btrfs: qgroup: Mo...
1549
  		if (bytenr < entry->bytenr) {
3368d001b   Qu Wenruo   btrfs: qgroup: Re...
1550
  			p = &(*p)->rb_left;
1418bae1c   Qu Wenruo   btrfs: qgroup: Mo...
1551
  		} else if (bytenr > entry->bytenr) {
3368d001b   Qu Wenruo   btrfs: qgroup: Re...
1552
  			p = &(*p)->rb_right;
1418bae1c   Qu Wenruo   btrfs: qgroup: Mo...
1553
1554
1555
1556
1557
1558
  		} else {
  			if (record->data_rsv && !entry->data_rsv) {
  				entry->data_rsv = record->data_rsv;
  				entry->data_rsv_refroot =
  					record->data_rsv_refroot;
  			}
cb93b52cc   Qu Wenruo   btrfs: qgroup: Re...
1559
  			return 1;
1418bae1c   Qu Wenruo   btrfs: qgroup: Mo...
1560
  		}
3368d001b   Qu Wenruo   btrfs: qgroup: Re...
1561
1562
1563
1564
  	}
  
  	rb_link_node(&record->node, parent_node, p);
  	rb_insert_color(&record->node, &delayed_refs->dirty_extent_root);
cb93b52cc   Qu Wenruo   btrfs: qgroup: Re...
1565
1566
  	return 0;
  }
fb235dc06   Qu Wenruo   btrfs: qgroup: Mo...
1567
1568
1569
1570
1571
1572
  int btrfs_qgroup_trace_extent_post(struct btrfs_fs_info *fs_info,
  				   struct btrfs_qgroup_extent_record *qrecord)
  {
  	struct ulist *old_root;
  	u64 bytenr = qrecord->bytenr;
  	int ret;
c995ab3cd   Zygo Blaxell   btrfs: add a flag...
1573
  	ret = btrfs_find_all_roots(NULL, fs_info, bytenr, 0, &old_root, false);
952bd3db0   Nikolay Borisov   btrfs: Ignore err...
1574
1575
1576
1577
1578
1579
1580
  	if (ret < 0) {
  		fs_info->qgroup_flags |= BTRFS_QGROUP_STATUS_FLAG_INCONSISTENT;
  		btrfs_warn(fs_info,
  "error accounting new delayed refs extent (err code: %d), quota inconsistent",
  			ret);
  		return 0;
  	}
fb235dc06   Qu Wenruo   btrfs: qgroup: Mo...
1581
1582
1583
1584
1585
1586
1587
1588
1589
1590
1591
  
  	/*
  	 * Here we don't need to get the lock of
  	 * trans->transaction->delayed_refs, since inserted qrecord won't
  	 * be deleted, only qrecord->node may be modified (new qrecord insert)
  	 *
  	 * So modifying qrecord->old_roots is safe here
  	 */
  	qrecord->old_roots = old_root;
  	return 0;
  }
a95f3aafd   Lu Fengqi   btrfs: qgroup: Dr...
1592
1593
  int btrfs_qgroup_trace_extent(struct btrfs_trans_handle *trans, u64 bytenr,
  			      u64 num_bytes, gfp_t gfp_flag)
cb93b52cc   Qu Wenruo   btrfs: qgroup: Re...
1594
  {
a95f3aafd   Lu Fengqi   btrfs: qgroup: Dr...
1595
  	struct btrfs_fs_info *fs_info = trans->fs_info;
cb93b52cc   Qu Wenruo   btrfs: qgroup: Re...
1596
1597
1598
  	struct btrfs_qgroup_extent_record *record;
  	struct btrfs_delayed_ref_root *delayed_refs;
  	int ret;
afcdd129e   Josef Bacik   Btrfs: add a flag...
1599
1600
  	if (!test_bit(BTRFS_FS_QUOTA_ENABLED, &fs_info->flags)
  	    || bytenr == 0 || num_bytes == 0)
cb93b52cc   Qu Wenruo   btrfs: qgroup: Re...
1601
  		return 0;
1418bae1c   Qu Wenruo   btrfs: qgroup: Mo...
1602
  	record = kzalloc(sizeof(*record), gfp_flag);
cb93b52cc   Qu Wenruo   btrfs: qgroup: Re...
1603
1604
1605
1606
1607
1608
1609
1610
1611
  	if (!record)
  		return -ENOMEM;
  
  	delayed_refs = &trans->transaction->delayed_refs;
  	record->bytenr = bytenr;
  	record->num_bytes = num_bytes;
  	record->old_roots = NULL;
  
  	spin_lock(&delayed_refs->lock);
2ff7e61e0   Jeff Mahoney   btrfs: take an fs...
1612
  	ret = btrfs_qgroup_trace_extent_nolock(fs_info, delayed_refs, record);
cb93b52cc   Qu Wenruo   btrfs: qgroup: Re...
1613
  	spin_unlock(&delayed_refs->lock);
fb235dc06   Qu Wenruo   btrfs: qgroup: Mo...
1614
  	if (ret > 0) {
cb93b52cc   Qu Wenruo   btrfs: qgroup: Re...
1615
  		kfree(record);
fb235dc06   Qu Wenruo   btrfs: qgroup: Mo...
1616
1617
1618
  		return 0;
  	}
  	return btrfs_qgroup_trace_extent_post(fs_info, record);
3368d001b   Qu Wenruo   btrfs: qgroup: Re...
1619
  }
33d1f05cc   Qu Wenruo   btrfs: Export and...
1620
  int btrfs_qgroup_trace_leaf_items(struct btrfs_trans_handle *trans,
33d1f05cc   Qu Wenruo   btrfs: Export and...
1621
1622
  				  struct extent_buffer *eb)
  {
8d38d7eb7   Lu Fengqi   btrfs: qgroup: Dr...
1623
  	struct btrfs_fs_info *fs_info = trans->fs_info;
33d1f05cc   Qu Wenruo   btrfs: Export and...
1624
1625
1626
1627
1628
1629
1630
  	int nr = btrfs_header_nritems(eb);
  	int i, extent_type, ret;
  	struct btrfs_key key;
  	struct btrfs_file_extent_item *fi;
  	u64 bytenr, num_bytes;
  
  	/* We can be called directly from walk_up_proc() */
0b246afa6   Jeff Mahoney   btrfs: root->fs_i...
1631
  	if (!test_bit(BTRFS_FS_QUOTA_ENABLED, &fs_info->flags))
33d1f05cc   Qu Wenruo   btrfs: Export and...
1632
1633
1634
1635
1636
1637
1638
1639
1640
1641
1642
1643
1644
1645
1646
1647
1648
1649
1650
1651
  		return 0;
  
  	for (i = 0; i < nr; i++) {
  		btrfs_item_key_to_cpu(eb, &key, i);
  
  		if (key.type != BTRFS_EXTENT_DATA_KEY)
  			continue;
  
  		fi = btrfs_item_ptr(eb, i, struct btrfs_file_extent_item);
  		/* filter out non qgroup-accountable extents  */
  		extent_type = btrfs_file_extent_type(eb, fi);
  
  		if (extent_type == BTRFS_FILE_EXTENT_INLINE)
  			continue;
  
  		bytenr = btrfs_file_extent_disk_bytenr(eb, fi);
  		if (!bytenr)
  			continue;
  
  		num_bytes = btrfs_file_extent_disk_num_bytes(eb, fi);
a95f3aafd   Lu Fengqi   btrfs: qgroup: Dr...
1652
1653
  		ret = btrfs_qgroup_trace_extent(trans, bytenr, num_bytes,
  						GFP_NOFS);
33d1f05cc   Qu Wenruo   btrfs: Export and...
1654
1655
1656
  		if (ret)
  			return ret;
  	}
cddf3b2cb   Jeff Mahoney   btrfs: add cond_r...
1657
  	cond_resched();
33d1f05cc   Qu Wenruo   btrfs: Export and...
1658
1659
1660
1661
1662
1663
1664
1665
1666
1667
1668
1669
1670
1671
1672
1673
1674
  	return 0;
  }
  
  /*
   * Walk up the tree from the bottom, freeing leaves and any interior
   * nodes which have had all slots visited. If a node (leaf or
   * interior) is freed, the node above it will have it's slot
   * incremented. The root node will never be freed.
   *
   * At the end of this function, we should have a path which has all
   * slots incremented to the next position for a search. If we need to
   * read a new node it will be NULL and the node above it will have the
   * correct slot selected for a later read.
   *
   * If we increment the root nodes slot counter past the number of
   * elements, 1 is returned to signal completion of the search.
   */
15b34517a   David Sterba   btrfs: remove unu...
1675
  static int adjust_slots_upwards(struct btrfs_path *path, int root_level)
33d1f05cc   Qu Wenruo   btrfs: Export and...
1676
1677
1678
1679
1680
1681
1682
1683
1684
1685
1686
1687
1688
1689
1690
1691
1692
1693
1694
1695
1696
1697
1698
1699
1700
1701
1702
1703
1704
1705
1706
1707
1708
1709
1710
1711
1712
1713
1714
1715
1716
1717
1718
1719
1720
  {
  	int level = 0;
  	int nr, slot;
  	struct extent_buffer *eb;
  
  	if (root_level == 0)
  		return 1;
  
  	while (level <= root_level) {
  		eb = path->nodes[level];
  		nr = btrfs_header_nritems(eb);
  		path->slots[level]++;
  		slot = path->slots[level];
  		if (slot >= nr || level == 0) {
  			/*
  			 * Don't free the root -  we will detect this
  			 * condition after our loop and return a
  			 * positive value for caller to stop walking the tree.
  			 */
  			if (level != root_level) {
  				btrfs_tree_unlock_rw(eb, path->locks[level]);
  				path->locks[level] = 0;
  
  				free_extent_buffer(eb);
  				path->nodes[level] = NULL;
  				path->slots[level] = 0;
  			}
  		} else {
  			/*
  			 * We have a valid slot to walk back down
  			 * from. Stop here so caller can process these
  			 * new nodes.
  			 */
  			break;
  		}
  
  		level++;
  	}
  
  	eb = path->nodes[root_level];
  	if (path->slots[root_level] >= btrfs_header_nritems(eb))
  		return 1;
  
  	return 0;
  }
25982561d   Qu Wenruo   btrfs: qgroup: In...
1721
1722
1723
1724
1725
1726
1727
1728
1729
1730
1731
1732
1733
1734
1735
1736
1737
1738
1739
1740
1741
1742
1743
1744
1745
1746
1747
1748
1749
1750
1751
1752
1753
1754
1755
1756
  /*
   * Helper function to trace a subtree tree block swap.
   *
   * The swap will happen in highest tree block, but there may be a lot of
   * tree blocks involved.
   *
   * For example:
   *  OO = Old tree blocks
   *  NN = New tree blocks allocated during balance
   *
   *           File tree (257)                  Reloc tree for 257
   * L2              OO                                NN
   *               /    \                            /    \
   * L1          OO      OO (a)                    OO      NN (a)
   *            / \     / \                       / \     / \
   * L0       OO   OO OO   OO                   OO   OO NN   NN
   *                  (b)  (c)                          (b)  (c)
   *
   * When calling qgroup_trace_extent_swap(), we will pass:
   * @src_eb = OO(a)
   * @dst_path = [ nodes[1] = NN(a), nodes[0] = NN(c) ]
   * @dst_level = 0
   * @root_level = 1
   *
   * In that case, qgroup_trace_extent_swap() will search from OO(a) to
   * reach OO(c), then mark both OO(c) and NN(c) as qgroup dirty.
   *
   * The main work of qgroup_trace_extent_swap() can be split into 3 parts:
   *
   * 1) Tree search from @src_eb
   *    It should acts as a simplified btrfs_search_slot().
   *    The key for search can be extracted from @dst_path->nodes[dst_level]
   *    (first key).
   *
   * 2) Mark the final tree blocks in @src_path and @dst_path qgroup dirty
   *    NOTE: In above case, OO(a) and NN(a) won't be marked qgroup dirty.
52042d8e8   Andrea Gelmini   btrfs: Fix typos ...
1757
   *    They should be marked during previous (@dst_level = 1) iteration.
25982561d   Qu Wenruo   btrfs: qgroup: In...
1758
1759
1760
1761
1762
1763
   *
   * 3) Mark file extents in leaves dirty
   *    We don't have good way to pick out new file extents only.
   *    So we still follow the old method by scanning all file extents in
   *    the leave.
   *
52042d8e8   Andrea Gelmini   btrfs: Fix typos ...
1764
   * This function can free us from keeping two paths, thus later we only need
25982561d   Qu Wenruo   btrfs: qgroup: In...
1765
1766
1767
1768
1769
   * to care about how to iterate all new tree blocks in reloc tree.
   */
  static int qgroup_trace_extent_swap(struct btrfs_trans_handle* trans,
  				    struct extent_buffer *src_eb,
  				    struct btrfs_path *dst_path,
3d0174f78   Qu Wenruo   btrfs: qgroup: On...
1770
1771
  				    int dst_level, int root_level,
  				    bool trace_leaf)
25982561d   Qu Wenruo   btrfs: qgroup: In...
1772
1773
1774
1775
1776
1777
1778
1779
1780
1781
1782
1783
1784
1785
1786
1787
1788
1789
1790
1791
1792
1793
1794
1795
1796
  {
  	struct btrfs_key key;
  	struct btrfs_path *src_path;
  	struct btrfs_fs_info *fs_info = trans->fs_info;
  	u32 nodesize = fs_info->nodesize;
  	int cur_level = root_level;
  	int ret;
  
  	BUG_ON(dst_level > root_level);
  	/* Level mismatch */
  	if (btrfs_header_level(src_eb) != root_level)
  		return -EINVAL;
  
  	src_path = btrfs_alloc_path();
  	if (!src_path) {
  		ret = -ENOMEM;
  		goto out;
  	}
  
  	if (dst_level)
  		btrfs_node_key_to_cpu(dst_path->nodes[dst_level], &key, 0);
  	else
  		btrfs_item_key_to_cpu(dst_path->nodes[dst_level], &key, 0);
  
  	/* For src_path */
67439dadb   David Sterba   btrfs: opencode e...
1797
  	atomic_inc(&src_eb->refs);
25982561d   Qu Wenruo   btrfs: qgroup: In...
1798
1799
1800
1801
1802
1803
1804
1805
1806
1807
1808
1809
1810
1811
1812
1813
1814
1815
1816
1817
1818
1819
1820
1821
1822
1823
1824
1825
1826
1827
1828
1829
1830
1831
1832
1833
  	src_path->nodes[root_level] = src_eb;
  	src_path->slots[root_level] = dst_path->slots[root_level];
  	src_path->locks[root_level] = 0;
  
  	/* A simplified version of btrfs_search_slot() */
  	while (cur_level >= dst_level) {
  		struct btrfs_key src_key;
  		struct btrfs_key dst_key;
  
  		if (src_path->nodes[cur_level] == NULL) {
  			struct btrfs_key first_key;
  			struct extent_buffer *eb;
  			int parent_slot;
  			u64 child_gen;
  			u64 child_bytenr;
  
  			eb = src_path->nodes[cur_level + 1];
  			parent_slot = src_path->slots[cur_level + 1];
  			child_bytenr = btrfs_node_blockptr(eb, parent_slot);
  			child_gen = btrfs_node_ptr_generation(eb, parent_slot);
  			btrfs_node_key_to_cpu(eb, &first_key, parent_slot);
  
  			eb = read_tree_block(fs_info, child_bytenr, child_gen,
  					     cur_level, &first_key);
  			if (IS_ERR(eb)) {
  				ret = PTR_ERR(eb);
  				goto out;
  			} else if (!extent_buffer_uptodate(eb)) {
  				free_extent_buffer(eb);
  				ret = -EIO;
  				goto out;
  			}
  
  			src_path->nodes[cur_level] = eb;
  
  			btrfs_tree_read_lock(eb);
300aa896e   David Sterba   btrfs: replace bt...
1834
  			btrfs_set_lock_blocking_read(eb);
25982561d   Qu Wenruo   btrfs: qgroup: In...
1835
1836
1837
1838
1839
1840
1841
1842
1843
1844
1845
1846
1847
1848
1849
1850
1851
1852
1853
1854
1855
1856
1857
1858
1859
1860
1861
1862
1863
1864
1865
1866
1867
1868
1869
1870
1871
1872
  			src_path->locks[cur_level] = BTRFS_READ_LOCK_BLOCKING;
  		}
  
  		src_path->slots[cur_level] = dst_path->slots[cur_level];
  		if (cur_level) {
  			btrfs_node_key_to_cpu(dst_path->nodes[cur_level],
  					&dst_key, dst_path->slots[cur_level]);
  			btrfs_node_key_to_cpu(src_path->nodes[cur_level],
  					&src_key, src_path->slots[cur_level]);
  		} else {
  			btrfs_item_key_to_cpu(dst_path->nodes[cur_level],
  					&dst_key, dst_path->slots[cur_level]);
  			btrfs_item_key_to_cpu(src_path->nodes[cur_level],
  					&src_key, src_path->slots[cur_level]);
  		}
  		/* Content mismatch, something went wrong */
  		if (btrfs_comp_cpu_keys(&dst_key, &src_key)) {
  			ret = -ENOENT;
  			goto out;
  		}
  		cur_level--;
  	}
  
  	/*
  	 * Now both @dst_path and @src_path have been populated, record the tree
  	 * blocks for qgroup accounting.
  	 */
  	ret = btrfs_qgroup_trace_extent(trans, src_path->nodes[dst_level]->start,
  			nodesize, GFP_NOFS);
  	if (ret < 0)
  		goto out;
  	ret = btrfs_qgroup_trace_extent(trans,
  			dst_path->nodes[dst_level]->start,
  			nodesize, GFP_NOFS);
  	if (ret < 0)
  		goto out;
  
  	/* Record leaf file extents */
3d0174f78   Qu Wenruo   btrfs: qgroup: On...
1873
  	if (dst_level == 0 && trace_leaf) {
25982561d   Qu Wenruo   btrfs: qgroup: In...
1874
1875
1876
1877
1878
1879
1880
1881
1882
  		ret = btrfs_qgroup_trace_leaf_items(trans, src_path->nodes[0]);
  		if (ret < 0)
  			goto out;
  		ret = btrfs_qgroup_trace_leaf_items(trans, dst_path->nodes[0]);
  	}
  out:
  	btrfs_free_path(src_path);
  	return ret;
  }
ea49f3e73   Qu Wenruo   btrfs: qgroup: In...
1883
1884
1885
1886
1887
1888
1889
1890
1891
1892
1893
1894
1895
1896
1897
1898
1899
1900
1901
  /*
   * Helper function to do recursive generation-aware depth-first search, to
   * locate all new tree blocks in a subtree of reloc tree.
   *
   * E.g. (OO = Old tree blocks, NN = New tree blocks, whose gen == last_snapshot)
   *         reloc tree
   * L2         NN (a)
   *          /    \
   * L1    OO        NN (b)
   *      /  \      /  \
   * L0  OO  OO    OO  NN
   *               (c) (d)
   * If we pass:
   * @dst_path = [ nodes[1] = NN(b), nodes[0] = NULL ],
   * @cur_level = 1
   * @root_level = 1
   *
   * We will iterate through tree blocks NN(b), NN(d) and info qgroup to trace
   * above tree blocks along with their counter parts in file tree.
52042d8e8   Andrea Gelmini   btrfs: Fix typos ...
1902
   * While during search, old tree blocks OO(c) will be skipped as tree block swap
ea49f3e73   Qu Wenruo   btrfs: qgroup: In...
1903
1904
1905
1906
1907
1908
   * won't affect OO(c).
   */
  static int qgroup_trace_new_subtree_blocks(struct btrfs_trans_handle* trans,
  					   struct extent_buffer *src_eb,
  					   struct btrfs_path *dst_path,
  					   int cur_level, int root_level,
3d0174f78   Qu Wenruo   btrfs: qgroup: On...
1909
  					   u64 last_snapshot, bool trace_leaf)
ea49f3e73   Qu Wenruo   btrfs: qgroup: In...
1910
1911
1912
1913
1914
1915
1916
1917
  {
  	struct btrfs_fs_info *fs_info = trans->fs_info;
  	struct extent_buffer *eb;
  	bool need_cleanup = false;
  	int ret = 0;
  	int i;
  
  	/* Level sanity check */
7ff2c2a1a   Nikolay Borisov   btrfs: Fix bound ...
1918
1919
  	if (cur_level < 0 || cur_level >= BTRFS_MAX_LEVEL - 1 ||
  	    root_level < 0 || root_level >= BTRFS_MAX_LEVEL - 1 ||
ea49f3e73   Qu Wenruo   btrfs: qgroup: In...
1920
1921
1922
1923
1924
1925
1926
1927
1928
1929
1930
1931
1932
1933
1934
1935
1936
1937
1938
1939
1940
1941
1942
1943
1944
1945
1946
1947
1948
1949
1950
1951
1952
1953
1954
1955
1956
1957
1958
1959
1960
1961
1962
1963
1964
1965
1966
1967
1968
1969
1970
1971
1972
1973
  	    root_level < cur_level) {
  		btrfs_err_rl(fs_info,
  			"%s: bad levels, cur_level=%d root_level=%d",
  			__func__, cur_level, root_level);
  		return -EUCLEAN;
  	}
  
  	/* Read the tree block if needed */
  	if (dst_path->nodes[cur_level] == NULL) {
  		struct btrfs_key first_key;
  		int parent_slot;
  		u64 child_gen;
  		u64 child_bytenr;
  
  		/*
  		 * dst_path->nodes[root_level] must be initialized before
  		 * calling this function.
  		 */
  		if (cur_level == root_level) {
  			btrfs_err_rl(fs_info,
  	"%s: dst_path->nodes[%d] not initialized, root_level=%d cur_level=%d",
  				__func__, root_level, root_level, cur_level);
  			return -EUCLEAN;
  		}
  
  		/*
  		 * We need to get child blockptr/gen from parent before we can
  		 * read it.
  		  */
  		eb = dst_path->nodes[cur_level + 1];
  		parent_slot = dst_path->slots[cur_level + 1];
  		child_bytenr = btrfs_node_blockptr(eb, parent_slot);
  		child_gen = btrfs_node_ptr_generation(eb, parent_slot);
  		btrfs_node_key_to_cpu(eb, &first_key, parent_slot);
  
  		/* This node is old, no need to trace */
  		if (child_gen < last_snapshot)
  			goto out;
  
  		eb = read_tree_block(fs_info, child_bytenr, child_gen,
  				     cur_level, &first_key);
  		if (IS_ERR(eb)) {
  			ret = PTR_ERR(eb);
  			goto out;
  		} else if (!extent_buffer_uptodate(eb)) {
  			free_extent_buffer(eb);
  			ret = -EIO;
  			goto out;
  		}
  
  		dst_path->nodes[cur_level] = eb;
  		dst_path->slots[cur_level] = 0;
  
  		btrfs_tree_read_lock(eb);
300aa896e   David Sterba   btrfs: replace bt...
1974
  		btrfs_set_lock_blocking_read(eb);
ea49f3e73   Qu Wenruo   btrfs: qgroup: In...
1975
1976
1977
1978
1979
1980
  		dst_path->locks[cur_level] = BTRFS_READ_LOCK_BLOCKING;
  		need_cleanup = true;
  	}
  
  	/* Now record this tree block and its counter part for qgroups */
  	ret = qgroup_trace_extent_swap(trans, src_eb, dst_path, cur_level,
3d0174f78   Qu Wenruo   btrfs: qgroup: On...
1981
  				       root_level, trace_leaf);
ea49f3e73   Qu Wenruo   btrfs: qgroup: In...
1982
1983
1984
1985
1986
1987
1988
1989
1990
1991
1992
1993
1994
1995
1996
1997
  	if (ret < 0)
  		goto cleanup;
  
  	eb = dst_path->nodes[cur_level];
  
  	if (cur_level > 0) {
  		/* Iterate all child tree blocks */
  		for (i = 0; i < btrfs_header_nritems(eb); i++) {
  			/* Skip old tree blocks as they won't be swapped */
  			if (btrfs_node_ptr_generation(eb, i) < last_snapshot)
  				continue;
  			dst_path->slots[cur_level] = i;
  
  			/* Recursive call (at most 7 times) */
  			ret = qgroup_trace_new_subtree_blocks(trans, src_eb,
  					dst_path, cur_level - 1, root_level,
3d0174f78   Qu Wenruo   btrfs: qgroup: On...
1998
  					last_snapshot, trace_leaf);
ea49f3e73   Qu Wenruo   btrfs: qgroup: In...
1999
2000
2001
2002
2003
2004
2005
2006
2007
2008
2009
2010
2011
2012
2013
2014
2015
2016
  			if (ret < 0)
  				goto cleanup;
  		}
  	}
  
  cleanup:
  	if (need_cleanup) {
  		/* Clean up */
  		btrfs_tree_unlock_rw(dst_path->nodes[cur_level],
  				     dst_path->locks[cur_level]);
  		free_extent_buffer(dst_path->nodes[cur_level]);
  		dst_path->nodes[cur_level] = NULL;
  		dst_path->slots[cur_level] = 0;
  		dst_path->locks[cur_level] = 0;
  	}
  out:
  	return ret;
  }
5aea1a4fc   Qu Wenruo   btrfs: qgroup: Re...
2017
2018
2019
2020
2021
2022
2023
2024
2025
2026
2027
2028
2029
2030
2031
2032
2033
2034
2035
2036
2037
2038
2039
2040
2041
2042
2043
2044
2045
2046
2047
2048
2049
2050
  static int qgroup_trace_subtree_swap(struct btrfs_trans_handle *trans,
  				struct extent_buffer *src_eb,
  				struct extent_buffer *dst_eb,
  				u64 last_snapshot, bool trace_leaf)
  {
  	struct btrfs_fs_info *fs_info = trans->fs_info;
  	struct btrfs_path *dst_path = NULL;
  	int level;
  	int ret;
  
  	if (!test_bit(BTRFS_FS_QUOTA_ENABLED, &fs_info->flags))
  		return 0;
  
  	/* Wrong parameter order */
  	if (btrfs_header_generation(src_eb) > btrfs_header_generation(dst_eb)) {
  		btrfs_err_rl(fs_info,
  		"%s: bad parameter order, src_gen=%llu dst_gen=%llu", __func__,
  			     btrfs_header_generation(src_eb),
  			     btrfs_header_generation(dst_eb));
  		return -EUCLEAN;
  	}
  
  	if (!extent_buffer_uptodate(src_eb) || !extent_buffer_uptodate(dst_eb)) {
  		ret = -EIO;
  		goto out;
  	}
  
  	level = btrfs_header_level(dst_eb);
  	dst_path = btrfs_alloc_path();
  	if (!dst_path) {
  		ret = -ENOMEM;
  		goto out;
  	}
  	/* For dst_path */
67439dadb   David Sterba   btrfs: opencode e...
2051
  	atomic_inc(&dst_eb->refs);
5aea1a4fc   Qu Wenruo   btrfs: qgroup: Re...
2052
2053
2054
2055
2056
2057
2058
2059
2060
2061
2062
2063
2064
2065
2066
2067
2068
  	dst_path->nodes[level] = dst_eb;
  	dst_path->slots[level] = 0;
  	dst_path->locks[level] = 0;
  
  	/* Do the generation aware breadth-first search */
  	ret = qgroup_trace_new_subtree_blocks(trans, src_eb, dst_path, level,
  					      level, last_snapshot, trace_leaf);
  	if (ret < 0)
  		goto out;
  	ret = 0;
  
  out:
  	btrfs_free_path(dst_path);
  	if (ret < 0)
  		fs_info->qgroup_flags |= BTRFS_QGROUP_STATUS_FLAG_INCONSISTENT;
  	return ret;
  }
33d1f05cc   Qu Wenruo   btrfs: Export and...
2069
  int btrfs_qgroup_trace_subtree(struct btrfs_trans_handle *trans,
33d1f05cc   Qu Wenruo   btrfs: Export and...
2070
2071
2072
  			       struct extent_buffer *root_eb,
  			       u64 root_gen, int root_level)
  {
deb406274   Lu Fengqi   btrfs: qgroup: Dr...
2073
  	struct btrfs_fs_info *fs_info = trans->fs_info;
33d1f05cc   Qu Wenruo   btrfs: Export and...
2074
2075
2076
2077
  	int ret = 0;
  	int level;
  	struct extent_buffer *eb = root_eb;
  	struct btrfs_path *path = NULL;
b6e6bca51   Nikolay Borisov   btrfs: qgroups: F...
2078
  	BUG_ON(root_level < 0 || root_level >= BTRFS_MAX_LEVEL);
33d1f05cc   Qu Wenruo   btrfs: Export and...
2079
  	BUG_ON(root_eb == NULL);
0b246afa6   Jeff Mahoney   btrfs: root->fs_i...
2080
  	if (!test_bit(BTRFS_FS_QUOTA_ENABLED, &fs_info->flags))
33d1f05cc   Qu Wenruo   btrfs: Export and...
2081
2082
2083
  		return 0;
  
  	if (!extent_buffer_uptodate(root_eb)) {
581c17604   Qu Wenruo   btrfs: Validate c...
2084
  		ret = btrfs_read_buffer(root_eb, root_gen, root_level, NULL);
33d1f05cc   Qu Wenruo   btrfs: Export and...
2085
2086
2087
2088
2089
  		if (ret)
  			goto out;
  	}
  
  	if (root_level == 0) {
8d38d7eb7   Lu Fengqi   btrfs: qgroup: Dr...
2090
  		ret = btrfs_qgroup_trace_leaf_items(trans, root_eb);
33d1f05cc   Qu Wenruo   btrfs: Export and...
2091
2092
2093
2094
2095
2096
2097
2098
2099
2100
2101
2102
2103
2104
2105
2106
  		goto out;
  	}
  
  	path = btrfs_alloc_path();
  	if (!path)
  		return -ENOMEM;
  
  	/*
  	 * Walk down the tree.  Missing extent blocks are filled in as
  	 * we go. Metadata is accounted every time we read a new
  	 * extent block.
  	 *
  	 * When we reach a leaf, we account for file extent items in it,
  	 * walk back up the tree (adjusting slot pointers as we go)
  	 * and restart the search process.
  	 */
67439dadb   David Sterba   btrfs: opencode e...
2107
  	atomic_inc(&root_eb->refs);	/* For path */
33d1f05cc   Qu Wenruo   btrfs: Export and...
2108
2109
2110
2111
2112
2113
2114
  	path->nodes[root_level] = root_eb;
  	path->slots[root_level] = 0;
  	path->locks[root_level] = 0; /* so release_path doesn't try to unlock */
  walk_down:
  	level = root_level;
  	while (level >= 0) {
  		if (path->nodes[level] == NULL) {
581c17604   Qu Wenruo   btrfs: Validate c...
2115
  			struct btrfs_key first_key;
33d1f05cc   Qu Wenruo   btrfs: Export and...
2116
2117
2118
2119
2120
2121
2122
2123
2124
2125
2126
2127
  			int parent_slot;
  			u64 child_gen;
  			u64 child_bytenr;
  
  			/*
  			 * We need to get child blockptr/gen from parent before
  			 * we can read it.
  			  */
  			eb = path->nodes[level + 1];
  			parent_slot = path->slots[level + 1];
  			child_bytenr = btrfs_node_blockptr(eb, parent_slot);
  			child_gen = btrfs_node_ptr_generation(eb, parent_slot);
581c17604   Qu Wenruo   btrfs: Validate c...
2128
  			btrfs_node_key_to_cpu(eb, &first_key, parent_slot);
33d1f05cc   Qu Wenruo   btrfs: Export and...
2129

581c17604   Qu Wenruo   btrfs: Validate c...
2130
2131
  			eb = read_tree_block(fs_info, child_bytenr, child_gen,
  					     level, &first_key);
33d1f05cc   Qu Wenruo   btrfs: Export and...
2132
2133
2134
2135
2136
2137
2138
2139
2140
2141
2142
2143
2144
  			if (IS_ERR(eb)) {
  				ret = PTR_ERR(eb);
  				goto out;
  			} else if (!extent_buffer_uptodate(eb)) {
  				free_extent_buffer(eb);
  				ret = -EIO;
  				goto out;
  			}
  
  			path->nodes[level] = eb;
  			path->slots[level] = 0;
  
  			btrfs_tree_read_lock(eb);
300aa896e   David Sterba   btrfs: replace bt...
2145
  			btrfs_set_lock_blocking_read(eb);
33d1f05cc   Qu Wenruo   btrfs: Export and...
2146
  			path->locks[level] = BTRFS_READ_LOCK_BLOCKING;
a95f3aafd   Lu Fengqi   btrfs: qgroup: Dr...
2147
  			ret = btrfs_qgroup_trace_extent(trans, child_bytenr,
0b246afa6   Jeff Mahoney   btrfs: root->fs_i...
2148
2149
  							fs_info->nodesize,
  							GFP_NOFS);
33d1f05cc   Qu Wenruo   btrfs: Export and...
2150
2151
2152
2153
2154
  			if (ret)
  				goto out;
  		}
  
  		if (level == 0) {
8d38d7eb7   Lu Fengqi   btrfs: qgroup: Dr...
2155
2156
  			ret = btrfs_qgroup_trace_leaf_items(trans,
  							    path->nodes[level]);
33d1f05cc   Qu Wenruo   btrfs: Export and...
2157
2158
2159
2160
  			if (ret)
  				goto out;
  
  			/* Nonzero return here means we completed our search */
15b34517a   David Sterba   btrfs: remove unu...
2161
  			ret = adjust_slots_upwards(path, root_level);
33d1f05cc   Qu Wenruo   btrfs: Export and...
2162
2163
2164
2165
2166
2167
2168
2169
2170
2171
2172
2173
2174
2175
2176
2177
  			if (ret)
  				break;
  
  			/* Restart search with new slots */
  			goto walk_down;
  		}
  
  		level--;
  	}
  
  	ret = 0;
  out:
  	btrfs_free_path(path);
  
  	return ret;
  }
d810ef2be   Qu Wenruo   btrfs: qgroup: Ad...
2178
2179
2180
2181
2182
2183
2184
2185
2186
2187
2188
2189
2190
2191
2192
2193
2194
2195
2196
2197
2198
2199
2200
2201
2202
  #define UPDATE_NEW	0
  #define UPDATE_OLD	1
  /*
   * Walk all of the roots that points to the bytenr and adjust their refcnts.
   */
  static int qgroup_update_refcnt(struct btrfs_fs_info *fs_info,
  				struct ulist *roots, struct ulist *tmp,
  				struct ulist *qgroups, u64 seq, int update_old)
  {
  	struct ulist_node *unode;
  	struct ulist_iterator uiter;
  	struct ulist_node *tmp_unode;
  	struct ulist_iterator tmp_uiter;
  	struct btrfs_qgroup *qg;
  	int ret = 0;
  
  	if (!roots)
  		return 0;
  	ULIST_ITER_INIT(&uiter);
  	while ((unode = ulist_next(roots, &uiter))) {
  		qg = find_qgroup_rb(fs_info, unode->val);
  		if (!qg)
  			continue;
  
  		ulist_reinit(tmp);
ef2fff64f   David Sterba   btrfs: rename hel...
2203
  		ret = ulist_add(qgroups, qg->qgroupid, qgroup_to_aux(qg),
d810ef2be   Qu Wenruo   btrfs: qgroup: Ad...
2204
2205
2206
  				GFP_ATOMIC);
  		if (ret < 0)
  			return ret;
ef2fff64f   David Sterba   btrfs: rename hel...
2207
  		ret = ulist_add(tmp, qg->qgroupid, qgroup_to_aux(qg), GFP_ATOMIC);
d810ef2be   Qu Wenruo   btrfs: qgroup: Ad...
2208
2209
2210
2211
2212
  		if (ret < 0)
  			return ret;
  		ULIST_ITER_INIT(&tmp_uiter);
  		while ((tmp_unode = ulist_next(tmp, &tmp_uiter))) {
  			struct btrfs_qgroup_list *glist;
ef2fff64f   David Sterba   btrfs: rename hel...
2213
  			qg = unode_aux_to_qgroup(tmp_unode);
d810ef2be   Qu Wenruo   btrfs: qgroup: Ad...
2214
2215
2216
2217
2218
2219
  			if (update_old)
  				btrfs_qgroup_update_old_refcnt(qg, seq, 1);
  			else
  				btrfs_qgroup_update_new_refcnt(qg, seq, 1);
  			list_for_each_entry(glist, &qg->groups, next_group) {
  				ret = ulist_add(qgroups, glist->group->qgroupid,
ef2fff64f   David Sterba   btrfs: rename hel...
2220
  						qgroup_to_aux(glist->group),
d810ef2be   Qu Wenruo   btrfs: qgroup: Ad...
2221
2222
2223
2224
  						GFP_ATOMIC);
  				if (ret < 0)
  					return ret;
  				ret = ulist_add(tmp, glist->group->qgroupid,
ef2fff64f   David Sterba   btrfs: rename hel...
2225
  						qgroup_to_aux(glist->group),
d810ef2be   Qu Wenruo   btrfs: qgroup: Ad...
2226
2227
2228
2229
2230
2231
2232
2233
  						GFP_ATOMIC);
  				if (ret < 0)
  					return ret;
  			}
  		}
  	}
  	return 0;
  }
fcebe4562   Josef Bacik   Btrfs: rework qgr...
2234
  /*
823ae5b8e   Qu Wenruo   btrfs: qgroup: Ad...
2235
2236
   * Update qgroup rfer/excl counters.
   * Rfer update is easy, codes can explain themselves.
e69bcee37   Qu Wenruo   btrfs: qgroup: Cl...
2237
   *
823ae5b8e   Qu Wenruo   btrfs: qgroup: Ad...
2238
2239
2240
2241
2242
2243
2244
2245
2246
2247
2248
2249
2250
   * Excl update is tricky, the update is split into 2 part.
   * Part 1: Possible exclusive <-> sharing detect:
   *	|	A	|	!A	|
   *  -------------------------------------
   *  B	|	*	|	-	|
   *  -------------------------------------
   *  !B	|	+	|	**	|
   *  -------------------------------------
   *
   * Conditions:
   * A:	cur_old_roots < nr_old_roots	(not exclusive before)
   * !A:	cur_old_roots == nr_old_roots	(possible exclusive before)
   * B:	cur_new_roots < nr_new_roots	(not exclusive now)
013276101   Nicholas D Steeves   btrfs: fix string...
2251
   * !B:	cur_new_roots == nr_new_roots	(possible exclusive now)
823ae5b8e   Qu Wenruo   btrfs: qgroup: Ad...
2252
2253
2254
2255
2256
2257
2258
2259
2260
2261
2262
2263
2264
2265
2266
2267
2268
2269
2270
2271
2272
2273
2274
2275
2276
2277
2278
2279
2280
2281
2282
2283
   *
   * Results:
   * +: Possible sharing -> exclusive	-: Possible exclusive -> sharing
   * *: Definitely not changed.		**: Possible unchanged.
   *
   * For !A and !B condition, the exception is cur_old/new_roots == 0 case.
   *
   * To make the logic clear, we first use condition A and B to split
   * combination into 4 results.
   *
   * Then, for result "+" and "-", check old/new_roots == 0 case, as in them
   * only on variant maybe 0.
   *
   * Lastly, check result **, since there are 2 variants maybe 0, split them
   * again(2x2).
   * But this time we don't need to consider other things, the codes and logic
   * is easy to understand now.
   */
  static int qgroup_update_counters(struct btrfs_fs_info *fs_info,
  				  struct ulist *qgroups,
  				  u64 nr_old_roots,
  				  u64 nr_new_roots,
  				  u64 num_bytes, u64 seq)
  {
  	struct ulist_node *unode;
  	struct ulist_iterator uiter;
  	struct btrfs_qgroup *qg;
  	u64 cur_new_count, cur_old_count;
  
  	ULIST_ITER_INIT(&uiter);
  	while ((unode = ulist_next(qgroups, &uiter))) {
  		bool dirty = false;
ef2fff64f   David Sterba   btrfs: rename hel...
2284
  		qg = unode_aux_to_qgroup(unode);
823ae5b8e   Qu Wenruo   btrfs: qgroup: Ad...
2285
2286
  		cur_old_count = btrfs_qgroup_get_old_refcnt(qg, seq);
  		cur_new_count = btrfs_qgroup_get_new_refcnt(qg, seq);
8b317901d   Qu Wenruo   btrfs: trace: All...
2287
2288
  		trace_qgroup_update_counters(fs_info, qg, cur_old_count,
  					     cur_new_count);
0f5dcf8de   Mark Fasheh   btrfs: Add qgroup...
2289

823ae5b8e   Qu Wenruo   btrfs: qgroup: Ad...
2290
2291
2292
2293
2294
2295
2296
2297
2298
2299
2300
2301
2302
2303
2304
2305
2306
2307
2308
2309
2310
2311
2312
2313
2314
2315
2316
2317
2318
2319
2320
2321
2322
2323
2324
2325
2326
2327
2328
2329
2330
2331
2332
2333
2334
2335
2336
2337
2338
2339
2340
2341
2342
2343
2344
2345
2346
2347
2348
2349
  		/* Rfer update part */
  		if (cur_old_count == 0 && cur_new_count > 0) {
  			qg->rfer += num_bytes;
  			qg->rfer_cmpr += num_bytes;
  			dirty = true;
  		}
  		if (cur_old_count > 0 && cur_new_count == 0) {
  			qg->rfer -= num_bytes;
  			qg->rfer_cmpr -= num_bytes;
  			dirty = true;
  		}
  
  		/* Excl update part */
  		/* Exclusive/none -> shared case */
  		if (cur_old_count == nr_old_roots &&
  		    cur_new_count < nr_new_roots) {
  			/* Exclusive -> shared */
  			if (cur_old_count != 0) {
  				qg->excl -= num_bytes;
  				qg->excl_cmpr -= num_bytes;
  				dirty = true;
  			}
  		}
  
  		/* Shared -> exclusive/none case */
  		if (cur_old_count < nr_old_roots &&
  		    cur_new_count == nr_new_roots) {
  			/* Shared->exclusive */
  			if (cur_new_count != 0) {
  				qg->excl += num_bytes;
  				qg->excl_cmpr += num_bytes;
  				dirty = true;
  			}
  		}
  
  		/* Exclusive/none -> exclusive/none case */
  		if (cur_old_count == nr_old_roots &&
  		    cur_new_count == nr_new_roots) {
  			if (cur_old_count == 0) {
  				/* None -> exclusive/none */
  
  				if (cur_new_count != 0) {
  					/* None -> exclusive */
  					qg->excl += num_bytes;
  					qg->excl_cmpr += num_bytes;
  					dirty = true;
  				}
  				/* None -> none, nothing changed */
  			} else {
  				/* Exclusive -> exclusive/none */
  
  				if (cur_new_count == 0) {
  					/* Exclusive -> none */
  					qg->excl -= num_bytes;
  					qg->excl_cmpr -= num_bytes;
  					dirty = true;
  				}
  				/* Exclusive -> exclusive, nothing changed */
  			}
  		}
c05f9429e   Qu Wenruo   btrfs: qgroup: Fi...
2350

823ae5b8e   Qu Wenruo   btrfs: qgroup: Ad...
2351
2352
2353
2354
2355
  		if (dirty)
  			qgroup_dirty(fs_info, qg);
  	}
  	return 0;
  }
5edfd9fdc   Qu Wenruo   btrfs: qgroup: Ad...
2356
2357
2358
2359
2360
2361
2362
2363
2364
2365
2366
2367
2368
2369
2370
2371
2372
2373
2374
2375
2376
2377
2378
2379
2380
2381
2382
2383
  /*
   * Check if the @roots potentially is a list of fs tree roots
   *
   * Return 0 for definitely not a fs/subvol tree roots ulist
   * Return 1 for possible fs/subvol tree roots in the list (considering an empty
   *          one as well)
   */
  static int maybe_fs_roots(struct ulist *roots)
  {
  	struct ulist_node *unode;
  	struct ulist_iterator uiter;
  
  	/* Empty one, still possible for fs roots */
  	if (!roots || roots->nnodes == 0)
  		return 1;
  
  	ULIST_ITER_INIT(&uiter);
  	unode = ulist_next(roots, &uiter);
  	if (!unode)
  		return 1;
  
  	/*
  	 * If it contains fs tree roots, then it must belong to fs/subvol
  	 * trees.
  	 * If it contains a non-fs tree, it won't be shared with fs/subvol trees.
  	 */
  	return is_fstree(unode->val);
  }
8696d7604   Lu Fengqi   btrfs: qgroup: Dr...
2384
2385
2386
  int btrfs_qgroup_account_extent(struct btrfs_trans_handle *trans, u64 bytenr,
  				u64 num_bytes, struct ulist *old_roots,
  				struct ulist *new_roots)
550d7a2ed   Qu Wenruo   btrfs: qgroup: Ad...
2387
  {
8696d7604   Lu Fengqi   btrfs: qgroup: Dr...
2388
  	struct btrfs_fs_info *fs_info = trans->fs_info;
550d7a2ed   Qu Wenruo   btrfs: qgroup: Ad...
2389
2390
2391
2392
2393
2394
  	struct ulist *qgroups = NULL;
  	struct ulist *tmp = NULL;
  	u64 seq;
  	u64 nr_new_roots = 0;
  	u64 nr_old_roots = 0;
  	int ret = 0;
26ef8493e   Johannes Thumshirn   btrfs: fix memory...
2395
2396
2397
2398
  	/*
  	 * If quotas get disabled meanwhile, the resouces need to be freed and
  	 * we can't just exit here.
  	 */
81353d50f   David Sterba   btrfs: check quot...
2399
  	if (!test_bit(BTRFS_FS_QUOTA_ENABLED, &fs_info->flags))
26ef8493e   Johannes Thumshirn   btrfs: fix memory...
2400
  		goto out_free;
81353d50f   David Sterba   btrfs: check quot...
2401

5edfd9fdc   Qu Wenruo   btrfs: qgroup: Ad...
2402
2403
2404
  	if (new_roots) {
  		if (!maybe_fs_roots(new_roots))
  			goto out_free;
550d7a2ed   Qu Wenruo   btrfs: qgroup: Ad...
2405
  		nr_new_roots = new_roots->nnodes;
5edfd9fdc   Qu Wenruo   btrfs: qgroup: Ad...
2406
2407
2408
2409
  	}
  	if (old_roots) {
  		if (!maybe_fs_roots(old_roots))
  			goto out_free;
550d7a2ed   Qu Wenruo   btrfs: qgroup: Ad...
2410
  		nr_old_roots = old_roots->nnodes;
5edfd9fdc   Qu Wenruo   btrfs: qgroup: Ad...
2411
2412
2413
2414
2415
  	}
  
  	/* Quick exit, either not fs tree roots, or won't affect any qgroup */
  	if (nr_old_roots == 0 && nr_new_roots == 0)
  		goto out_free;
550d7a2ed   Qu Wenruo   btrfs: qgroup: Ad...
2416

550d7a2ed   Qu Wenruo   btrfs: qgroup: Ad...
2417
  	BUG_ON(!fs_info->quota_root);
c9f6f3cd1   Qu Wenruo   btrfs: qgroup: Al...
2418
2419
  	trace_btrfs_qgroup_account_extent(fs_info, trans->transid, bytenr,
  					num_bytes, nr_old_roots, nr_new_roots);
0f5dcf8de   Mark Fasheh   btrfs: Add qgroup...
2420

550d7a2ed   Qu Wenruo   btrfs: qgroup: Ad...
2421
2422
2423
2424
2425
2426
2427
2428
2429
2430
2431
2432
2433
2434
2435
2436
2437
2438
2439
2440
2441
2442
2443
2444
2445
2446
2447
2448
2449
2450
2451
2452
2453
2454
2455
2456
2457
2458
2459
2460
2461
2462
2463
2464
2465
2466
2467
2468
2469
2470
2471
2472
  	qgroups = ulist_alloc(GFP_NOFS);
  	if (!qgroups) {
  		ret = -ENOMEM;
  		goto out_free;
  	}
  	tmp = ulist_alloc(GFP_NOFS);
  	if (!tmp) {
  		ret = -ENOMEM;
  		goto out_free;
  	}
  
  	mutex_lock(&fs_info->qgroup_rescan_lock);
  	if (fs_info->qgroup_flags & BTRFS_QGROUP_STATUS_FLAG_RESCAN) {
  		if (fs_info->qgroup_rescan_progress.objectid <= bytenr) {
  			mutex_unlock(&fs_info->qgroup_rescan_lock);
  			ret = 0;
  			goto out_free;
  		}
  	}
  	mutex_unlock(&fs_info->qgroup_rescan_lock);
  
  	spin_lock(&fs_info->qgroup_lock);
  	seq = fs_info->qgroup_seq;
  
  	/* Update old refcnts using old_roots */
  	ret = qgroup_update_refcnt(fs_info, old_roots, tmp, qgroups, seq,
  				   UPDATE_OLD);
  	if (ret < 0)
  		goto out;
  
  	/* Update new refcnts using new_roots */
  	ret = qgroup_update_refcnt(fs_info, new_roots, tmp, qgroups, seq,
  				   UPDATE_NEW);
  	if (ret < 0)
  		goto out;
  
  	qgroup_update_counters(fs_info, qgroups, nr_old_roots, nr_new_roots,
  			       num_bytes, seq);
  
  	/*
  	 * Bump qgroup_seq to avoid seq overlap
  	 */
  	fs_info->qgroup_seq += max(nr_old_roots, nr_new_roots) + 1;
  out:
  	spin_unlock(&fs_info->qgroup_lock);
  out_free:
  	ulist_free(tmp);
  	ulist_free(qgroups);
  	ulist_free(old_roots);
  	ulist_free(new_roots);
  	return ret;
  }
460fb20a4   Nikolay Borisov   btrfs: Drop fs_in...
2473
  int btrfs_qgroup_account_extents(struct btrfs_trans_handle *trans)
550d7a2ed   Qu Wenruo   btrfs: qgroup: Ad...
2474
  {
460fb20a4   Nikolay Borisov   btrfs: Drop fs_in...
2475
  	struct btrfs_fs_info *fs_info = trans->fs_info;
550d7a2ed   Qu Wenruo   btrfs: qgroup: Ad...
2476
2477
2478
2479
  	struct btrfs_qgroup_extent_record *record;
  	struct btrfs_delayed_ref_root *delayed_refs;
  	struct ulist *new_roots = NULL;
  	struct rb_node *node;
c337e7b02   Qu Wenruo   btrfs: qgroup: In...
2480
  	u64 num_dirty_extents = 0;
9086db86e   Qu Wenruo   btrfs: qgroup: Ad...
2481
  	u64 qgroup_to_skip;
550d7a2ed   Qu Wenruo   btrfs: qgroup: Ad...
2482
2483
2484
  	int ret = 0;
  
  	delayed_refs = &trans->transaction->delayed_refs;
9086db86e   Qu Wenruo   btrfs: qgroup: Ad...
2485
  	qgroup_to_skip = delayed_refs->qgroup_to_skip;
550d7a2ed   Qu Wenruo   btrfs: qgroup: Ad...
2486
2487
2488
  	while ((node = rb_first(&delayed_refs->dirty_extent_root))) {
  		record = rb_entry(node, struct btrfs_qgroup_extent_record,
  				  node);
c337e7b02   Qu Wenruo   btrfs: qgroup: In...
2489
  		num_dirty_extents++;
bc074524e   Jeff Mahoney   btrfs: prefix fsi...
2490
  		trace_btrfs_qgroup_account_extents(fs_info, record);
0f5dcf8de   Mark Fasheh   btrfs: Add qgroup...
2491

550d7a2ed   Qu Wenruo   btrfs: qgroup: Ad...
2492
2493
  		if (!ret) {
  			/*
d1b8b94a2   Qu Wenruo   btrfs: qgroup: Cl...
2494
2495
2496
2497
2498
2499
2500
  			 * Old roots should be searched when inserting qgroup
  			 * extent record
  			 */
  			if (WARN_ON(!record->old_roots)) {
  				/* Search commit root to find old_roots */
  				ret = btrfs_find_all_roots(NULL, fs_info,
  						record->bytenr, 0,
c995ab3cd   Zygo Blaxell   btrfs: add a flag...
2501
  						&record->old_roots, false);
d1b8b94a2   Qu Wenruo   btrfs: qgroup: Cl...
2502
2503
2504
  				if (ret < 0)
  					goto cleanup;
  			}
1418bae1c   Qu Wenruo   btrfs: qgroup: Mo...
2505
2506
2507
2508
2509
  			/* Free the reserved data space */
  			btrfs_qgroup_free_refroot(fs_info,
  					record->data_rsv_refroot,
  					record->data_rsv,
  					BTRFS_QGROUP_RSV_DATA);
d1b8b94a2   Qu Wenruo   btrfs: qgroup: Cl...
2510
  			/*
de47c9d3f   Edmund Nadolski   btrfs: replace ha...
2511
  			 * Use SEQ_LAST as time_seq to do special search, which
550d7a2ed   Qu Wenruo   btrfs: qgroup: Ad...
2512
2513
2514
2515
  			 * doesn't lock tree or delayed_refs and search current
  			 * root. It's safe inside commit_transaction().
  			 */
  			ret = btrfs_find_all_roots(trans, fs_info,
c995ab3cd   Zygo Blaxell   btrfs: add a flag...
2516
  				record->bytenr, SEQ_LAST, &new_roots, false);
550d7a2ed   Qu Wenruo   btrfs: qgroup: Ad...
2517
2518
  			if (ret < 0)
  				goto cleanup;
d1b8b94a2   Qu Wenruo   btrfs: qgroup: Cl...
2519
  			if (qgroup_to_skip) {
9086db86e   Qu Wenruo   btrfs: qgroup: Ad...
2520
  				ulist_del(new_roots, qgroup_to_skip, 0);
d1b8b94a2   Qu Wenruo   btrfs: qgroup: Cl...
2521
2522
2523
  				ulist_del(record->old_roots, qgroup_to_skip,
  					  0);
  			}
8696d7604   Lu Fengqi   btrfs: qgroup: Dr...
2524
2525
2526
2527
  			ret = btrfs_qgroup_account_extent(trans, record->bytenr,
  							  record->num_bytes,
  							  record->old_roots,
  							  new_roots);
550d7a2ed   Qu Wenruo   btrfs: qgroup: Ad...
2528
2529
2530
2531
2532
2533
2534
2535
2536
2537
2538
  			record->old_roots = NULL;
  			new_roots = NULL;
  		}
  cleanup:
  		ulist_free(record->old_roots);
  		ulist_free(new_roots);
  		new_roots = NULL;
  		rb_erase(node, &delayed_refs->dirty_extent_root);
  		kfree(record);
  
  	}
c337e7b02   Qu Wenruo   btrfs: qgroup: In...
2539
2540
  	trace_qgroup_num_dirty_extents(fs_info, trans->transid,
  				       num_dirty_extents);
550d7a2ed   Qu Wenruo   btrfs: qgroup: Ad...
2541
2542
  	return ret;
  }
fcebe4562   Josef Bacik   Btrfs: rework qgr...
2543
  /*
bed92eae2   Arne Jansen   Btrfs: qgroup imp...
2544
2545
   * called from commit_transaction. Writes all changed qgroups to disk.
   */
280f8bd2c   Lu Fengqi   btrfs: qgroup: Dr...
2546
  int btrfs_run_qgroups(struct btrfs_trans_handle *trans)
bed92eae2   Arne Jansen   Btrfs: qgroup imp...
2547
  {
280f8bd2c   Lu Fengqi   btrfs: qgroup: Dr...
2548
  	struct btrfs_fs_info *fs_info = trans->fs_info;
bed92eae2   Arne Jansen   Btrfs: qgroup imp...
2549
  	int ret = 0;
e3b0edd29   Marcos Paulo de Souza   btrfs: qgroup: re...
2550
  	if (!fs_info->quota_root)
5d23515be   Nikolay Borisov   btrfs: Move qgrou...
2551
  		return ret;
bed92eae2   Arne Jansen   Btrfs: qgroup imp...
2552
2553
2554
2555
2556
2557
2558
2559
  
  	spin_lock(&fs_info->qgroup_lock);
  	while (!list_empty(&fs_info->dirty_qgroups)) {
  		struct btrfs_qgroup *qgroup;
  		qgroup = list_first_entry(&fs_info->dirty_qgroups,
  					  struct btrfs_qgroup, dirty);
  		list_del_init(&qgroup->dirty);
  		spin_unlock(&fs_info->qgroup_lock);
3e07e9a09   Lu Fengqi   btrfs: qgroup: Dr...
2560
  		ret = update_qgroup_info_item(trans, qgroup);
bed92eae2   Arne Jansen   Btrfs: qgroup imp...
2561
2562
  		if (ret)
  			fs_info->qgroup_flags |=
d3001ed3a   Dongsheng Yang   btrfs: qgroup: up...
2563
  					BTRFS_QGROUP_STATUS_FLAG_INCONSISTENT;
ac8a866af   Lu Fengqi   btrfs: qgroup: Dr...
2564
  		ret = update_qgroup_limit_item(trans, qgroup);
d3001ed3a   Dongsheng Yang   btrfs: qgroup: up...
2565
2566
  		if (ret)
  			fs_info->qgroup_flags |=
bed92eae2   Arne Jansen   Btrfs: qgroup imp...
2567
2568
2569
  					BTRFS_QGROUP_STATUS_FLAG_INCONSISTENT;
  		spin_lock(&fs_info->qgroup_lock);
  	}
afcdd129e   Josef Bacik   Btrfs: add a flag...
2570
  	if (test_bit(BTRFS_FS_QUOTA_ENABLED, &fs_info->flags))
bed92eae2   Arne Jansen   Btrfs: qgroup imp...
2571
2572
2573
2574
  		fs_info->qgroup_flags |= BTRFS_QGROUP_STATUS_FLAG_ON;
  	else
  		fs_info->qgroup_flags &= ~BTRFS_QGROUP_STATUS_FLAG_ON;
  	spin_unlock(&fs_info->qgroup_lock);
2e980acdd   Lu Fengqi   btrfs: qgroup: Dr...
2575
  	ret = update_qgroup_status_item(trans);
bed92eae2   Arne Jansen   Btrfs: qgroup imp...
2576
2577
  	if (ret)
  		fs_info->qgroup_flags |= BTRFS_QGROUP_STATUS_FLAG_INCONSISTENT;
bed92eae2   Arne Jansen   Btrfs: qgroup imp...
2578
2579
2580
2581
  	return ret;
  }
  
  /*
013276101   Nicholas D Steeves   btrfs: fix string...
2582
   * Copy the accounting information between qgroups. This is necessary
918c2ee10   Mark Fasheh   btrfs: handle non...
2583
2584
2585
   * when a snapshot or a subvolume is created. Throwing an error will
   * cause a transaction abort so we take extra care here to only error
   * when a readonly fs is a reasonable outcome.
bed92eae2   Arne Jansen   Btrfs: qgroup imp...
2586
   */
a93774225   Lu Fengqi   btrfs: qgroup: Dr...
2587
2588
  int btrfs_qgroup_inherit(struct btrfs_trans_handle *trans, u64 srcid,
  			 u64 objectid, struct btrfs_qgroup_inherit *inherit)
bed92eae2   Arne Jansen   Btrfs: qgroup imp...
2589
2590
2591
2592
  {
  	int ret = 0;
  	int i;
  	u64 *i_qgroups;
e88439deb   Qu Wenruo   btrfs: qgroup: Do...
2593
  	bool committing = false;
a93774225   Lu Fengqi   btrfs: qgroup: Dr...
2594
  	struct btrfs_fs_info *fs_info = trans->fs_info;
552f0329c   Filipe Manana   Btrfs: fix race b...
2595
  	struct btrfs_root *quota_root;
bed92eae2   Arne Jansen   Btrfs: qgroup imp...
2596
2597
  	struct btrfs_qgroup *srcgroup;
  	struct btrfs_qgroup *dstgroup;
cbab8ade5   Qu Wenruo   btrfs: qgroup: ma...
2598
  	bool need_rescan = false;
bed92eae2   Arne Jansen   Btrfs: qgroup imp...
2599
  	u32 level_size = 0;
3f5e2d3b3   Wang Shilong   Btrfs: fix missin...
2600
  	u64 nums;
bed92eae2   Arne Jansen   Btrfs: qgroup imp...
2601

e88439deb   Qu Wenruo   btrfs: qgroup: Do...
2602
2603
2604
2605
2606
2607
2608
2609
2610
2611
2612
2613
2614
2615
2616
2617
2618
2619
2620
  	/*
  	 * There are only two callers of this function.
  	 *
  	 * One in create_subvol() in the ioctl context, which needs to hold
  	 * the qgroup_ioctl_lock.
  	 *
  	 * The other one in create_pending_snapshot() where no other qgroup
  	 * code can modify the fs as they all need to either start a new trans
  	 * or hold a trans handler, thus we don't need to hold
  	 * qgroup_ioctl_lock.
  	 * This would avoid long and complex lock chain and make lockdep happy.
  	 */
  	spin_lock(&fs_info->trans_lock);
  	if (trans->transaction->state == TRANS_STATE_COMMIT_DOING)
  		committing = true;
  	spin_unlock(&fs_info->trans_lock);
  
  	if (!committing)
  		mutex_lock(&fs_info->qgroup_ioctl_lock);
afcdd129e   Josef Bacik   Btrfs: add a flag...
2621
  	if (!test_bit(BTRFS_FS_QUOTA_ENABLED, &fs_info->flags))
f2f6ed3d5   Wang Shilong   Btrfs: introduce ...
2622
  		goto out;
bed92eae2   Arne Jansen   Btrfs: qgroup imp...
2623

552f0329c   Filipe Manana   Btrfs: fix race b...
2624
  	quota_root = fs_info->quota_root;
f2f6ed3d5   Wang Shilong   Btrfs: introduce ...
2625
2626
2627
2628
  	if (!quota_root) {
  		ret = -EINVAL;
  		goto out;
  	}
bed92eae2   Arne Jansen   Btrfs: qgroup imp...
2629

3f5e2d3b3   Wang Shilong   Btrfs: fix missin...
2630
2631
2632
2633
2634
2635
  	if (inherit) {
  		i_qgroups = (u64 *)(inherit + 1);
  		nums = inherit->num_qgroups + 2 * inherit->num_ref_copies +
  		       2 * inherit->num_excl_copies;
  		for (i = 0; i < nums; ++i) {
  			srcgroup = find_qgroup_rb(fs_info, *i_qgroups);
09870d277   Dongsheng Yang   btrfs: qgroup: re...
2636

918c2ee10   Mark Fasheh   btrfs: handle non...
2637
2638
2639
2640
2641
2642
2643
  			/*
  			 * Zero out invalid groups so we can ignore
  			 * them later.
  			 */
  			if (!srcgroup ||
  			    ((srcgroup->qgroupid >> 48) <= (objectid >> 48)))
  				*i_qgroups = 0ULL;
3f5e2d3b3   Wang Shilong   Btrfs: fix missin...
2644
2645
2646
  			++i_qgroups;
  		}
  	}
bed92eae2   Arne Jansen   Btrfs: qgroup imp...
2647
2648
2649
2650
2651
2652
  	/*
  	 * create a tracking group for the subvol itself
  	 */
  	ret = add_qgroup_item(trans, quota_root, objectid);
  	if (ret)
  		goto out;
bed92eae2   Arne Jansen   Btrfs: qgroup imp...
2653
2654
2655
2656
2657
  	/*
  	 * add qgroup to all inherited groups
  	 */
  	if (inherit) {
  		i_qgroups = (u64 *)(inherit + 1);
918c2ee10   Mark Fasheh   btrfs: handle non...
2658
2659
2660
  		for (i = 0; i < inherit->num_qgroups; ++i, ++i_qgroups) {
  			if (*i_qgroups == 0)
  				continue;
711169c40   Lu Fengqi   btrfs: qgroup: Dr...
2661
2662
  			ret = add_qgroup_relation_item(trans, objectid,
  						       *i_qgroups);
918c2ee10   Mark Fasheh   btrfs: handle non...
2663
  			if (ret && ret != -EEXIST)
bed92eae2   Arne Jansen   Btrfs: qgroup imp...
2664
  				goto out;
711169c40   Lu Fengqi   btrfs: qgroup: Dr...
2665
2666
  			ret = add_qgroup_relation_item(trans, *i_qgroups,
  						       objectid);
918c2ee10   Mark Fasheh   btrfs: handle non...
2667
  			if (ret && ret != -EEXIST)
bed92eae2   Arne Jansen   Btrfs: qgroup imp...
2668
  				goto out;
bed92eae2   Arne Jansen   Btrfs: qgroup imp...
2669
  		}
918c2ee10   Mark Fasheh   btrfs: handle non...
2670
  		ret = 0;
bed92eae2   Arne Jansen   Btrfs: qgroup imp...
2671
2672
2673
2674
2675
2676
  	}
  
  
  	spin_lock(&fs_info->qgroup_lock);
  
  	dstgroup = add_qgroup_rb(fs_info, objectid);
57a5a8820   Dan Carpenter   Btrfs: checking f...
2677
2678
  	if (IS_ERR(dstgroup)) {
  		ret = PTR_ERR(dstgroup);
bed92eae2   Arne Jansen   Btrfs: qgroup imp...
2679
  		goto unlock;
57a5a8820   Dan Carpenter   Btrfs: checking f...
2680
  	}
bed92eae2   Arne Jansen   Btrfs: qgroup imp...
2681

e8c8541ac   Dongsheng Yang   btrfs: qgroup: up...
2682
  	if (inherit && inherit->flags & BTRFS_QGROUP_INHERIT_SET_LIMITS) {
e8c8541ac   Dongsheng Yang   btrfs: qgroup: up...
2683
2684
2685
2686
2687
  		dstgroup->lim_flags = inherit->lim.flags;
  		dstgroup->max_rfer = inherit->lim.max_rfer;
  		dstgroup->max_excl = inherit->lim.max_excl;
  		dstgroup->rsv_rfer = inherit->lim.rsv_rfer;
  		dstgroup->rsv_excl = inherit->lim.rsv_excl;
1510e71c6   Dongsheng Yang   btrfs: qgroup: co...
2688

ac8a866af   Lu Fengqi   btrfs: qgroup: Dr...
2689
  		ret = update_qgroup_limit_item(trans, dstgroup);
1510e71c6   Dongsheng Yang   btrfs: qgroup: co...
2690
2691
  		if (ret) {
  			fs_info->qgroup_flags |= BTRFS_QGROUP_STATUS_FLAG_INCONSISTENT;
5d163e0e6   Jeff Mahoney   btrfs: unsplit pr...
2692
2693
2694
  			btrfs_info(fs_info,
  				   "unable to update quota limit for %llu",
  				   dstgroup->qgroupid);
1510e71c6   Dongsheng Yang   btrfs: qgroup: co...
2695
2696
  			goto unlock;
  		}
e8c8541ac   Dongsheng Yang   btrfs: qgroup: up...
2697
  	}
bed92eae2   Arne Jansen   Btrfs: qgroup imp...
2698
2699
  	if (srcid) {
  		srcgroup = find_qgroup_rb(fs_info, srcid);
f3a87f1b0   Chris Mason   Revert "Btrfs: fi...
2700
  		if (!srcgroup)
bed92eae2   Arne Jansen   Btrfs: qgroup imp...
2701
  			goto unlock;
fcebe4562   Josef Bacik   Btrfs: rework qgr...
2702
2703
2704
2705
2706
2707
  
  		/*
  		 * We call inherit after we clone the root in order to make sure
  		 * our counts don't go crazy, so at this point the only
  		 * difference between the two roots should be the root node.
  		 */
c8389d4c0   Lu Fengqi   btrfs: qgroup: cl...
2708
  		level_size = fs_info->nodesize;
fcebe4562   Josef Bacik   Btrfs: rework qgr...
2709
2710
2711
2712
  		dstgroup->rfer = srcgroup->rfer;
  		dstgroup->rfer_cmpr = srcgroup->rfer_cmpr;
  		dstgroup->excl = level_size;
  		dstgroup->excl_cmpr = level_size;
bed92eae2   Arne Jansen   Btrfs: qgroup imp...
2713
2714
  		srcgroup->excl = level_size;
  		srcgroup->excl_cmpr = level_size;
3eeb4d597   Dongsheng Yang   btrfs: qgroup: in...
2715
2716
2717
2718
2719
2720
2721
  
  		/* inherit the limit info */
  		dstgroup->lim_flags = srcgroup->lim_flags;
  		dstgroup->max_rfer = srcgroup->max_rfer;
  		dstgroup->max_excl = srcgroup->max_excl;
  		dstgroup->rsv_rfer = srcgroup->rsv_rfer;
  		dstgroup->rsv_excl = srcgroup->rsv_excl;
bed92eae2   Arne Jansen   Btrfs: qgroup imp...
2722
2723
2724
  		qgroup_dirty(fs_info, dstgroup);
  		qgroup_dirty(fs_info, srcgroup);
  	}
f3a87f1b0   Chris Mason   Revert "Btrfs: fi...
2725
  	if (!inherit)
bed92eae2   Arne Jansen   Btrfs: qgroup imp...
2726
2727
2728
2729
  		goto unlock;
  
  	i_qgroups = (u64 *)(inherit + 1);
  	for (i = 0; i < inherit->num_qgroups; ++i) {
918c2ee10   Mark Fasheh   btrfs: handle non...
2730
  		if (*i_qgroups) {
0b246afa6   Jeff Mahoney   btrfs: root->fs_i...
2731
  			ret = add_relation_rb(fs_info, objectid, *i_qgroups);
918c2ee10   Mark Fasheh   btrfs: handle non...
2732
2733
2734
  			if (ret)
  				goto unlock;
  		}
bed92eae2   Arne Jansen   Btrfs: qgroup imp...
2735
  		++i_qgroups;
cbab8ade5   Qu Wenruo   btrfs: qgroup: ma...
2736
2737
2738
2739
2740
2741
2742
  
  		/*
  		 * If we're doing a snapshot, and adding the snapshot to a new
  		 * qgroup, the numbers are guaranteed to be incorrect.
  		 */
  		if (srcid)
  			need_rescan = true;
bed92eae2   Arne Jansen   Btrfs: qgroup imp...
2743
  	}
918c2ee10   Mark Fasheh   btrfs: handle non...
2744
  	for (i = 0; i <  inherit->num_ref_copies; ++i, i_qgroups += 2) {
bed92eae2   Arne Jansen   Btrfs: qgroup imp...
2745
2746
  		struct btrfs_qgroup *src;
  		struct btrfs_qgroup *dst;
918c2ee10   Mark Fasheh   btrfs: handle non...
2747
2748
  		if (!i_qgroups[0] || !i_qgroups[1])
  			continue;
bed92eae2   Arne Jansen   Btrfs: qgroup imp...
2749
2750
2751
2752
2753
2754
2755
2756
2757
2758
  		src = find_qgroup_rb(fs_info, i_qgroups[0]);
  		dst = find_qgroup_rb(fs_info, i_qgroups[1]);
  
  		if (!src || !dst) {
  			ret = -EINVAL;
  			goto unlock;
  		}
  
  		dst->rfer = src->rfer - level_size;
  		dst->rfer_cmpr = src->rfer_cmpr - level_size;
cbab8ade5   Qu Wenruo   btrfs: qgroup: ma...
2759
2760
2761
  
  		/* Manually tweaking numbers certainly needs a rescan */
  		need_rescan = true;
bed92eae2   Arne Jansen   Btrfs: qgroup imp...
2762
  	}
918c2ee10   Mark Fasheh   btrfs: handle non...
2763
  	for (i = 0; i <  inherit->num_excl_copies; ++i, i_qgroups += 2) {
bed92eae2   Arne Jansen   Btrfs: qgroup imp...
2764
2765
  		struct btrfs_qgroup *src;
  		struct btrfs_qgroup *dst;
918c2ee10   Mark Fasheh   btrfs: handle non...
2766
2767
  		if (!i_qgroups[0] || !i_qgroups[1])
  			continue;
bed92eae2   Arne Jansen   Btrfs: qgroup imp...
2768
2769
2770
2771
2772
2773
2774
2775
2776
2777
  		src = find_qgroup_rb(fs_info, i_qgroups[0]);
  		dst = find_qgroup_rb(fs_info, i_qgroups[1]);
  
  		if (!src || !dst) {
  			ret = -EINVAL;
  			goto unlock;
  		}
  
  		dst->excl = src->excl + level_size;
  		dst->excl_cmpr = src->excl_cmpr + level_size;
cbab8ade5   Qu Wenruo   btrfs: qgroup: ma...
2778
  		need_rescan = true;
bed92eae2   Arne Jansen   Btrfs: qgroup imp...
2779
2780
2781
2782
  	}
  
  unlock:
  	spin_unlock(&fs_info->qgroup_lock);
49e5fb462   Qu Wenruo   btrfs: qgroup: ex...
2783
2784
  	if (!ret)
  		ret = btrfs_sysfs_add_one_qgroup(fs_info, dstgroup);
bed92eae2   Arne Jansen   Btrfs: qgroup imp...
2785
  out:
e88439deb   Qu Wenruo   btrfs: qgroup: Do...
2786
2787
  	if (!committing)
  		mutex_unlock(&fs_info->qgroup_ioctl_lock);
cbab8ade5   Qu Wenruo   btrfs: qgroup: ma...
2788
2789
  	if (need_rescan)
  		fs_info->qgroup_flags |= BTRFS_QGROUP_STATUS_FLAG_INCONSISTENT;
bed92eae2   Arne Jansen   Btrfs: qgroup imp...
2790
2791
  	return ret;
  }
adca4d945   Qu Wenruo   btrfs: qgroup: re...
2792
  static bool qgroup_check_limits(const struct btrfs_qgroup *qg, u64 num_bytes)
003d7c59e   Jeff Mahoney   btrfs: allow unli...
2793
2794
  {
  	if ((qg->lim_flags & BTRFS_QGROUP_LIMIT_MAX_RFER) &&
dba213242   Qu Wenruo   btrfs: qgroup: Ma...
2795
  	    qgroup_rsv_total(qg) + (s64)qg->rfer + num_bytes > qg->max_rfer)
003d7c59e   Jeff Mahoney   btrfs: allow unli...
2796
2797
2798
  		return false;
  
  	if ((qg->lim_flags & BTRFS_QGROUP_LIMIT_MAX_EXCL) &&
dba213242   Qu Wenruo   btrfs: qgroup: Ma...
2799
  	    qgroup_rsv_total(qg) + (s64)qg->excl + num_bytes > qg->max_excl)
003d7c59e   Jeff Mahoney   btrfs: allow unli...
2800
2801
2802
2803
  		return false;
  
  	return true;
  }
dba213242   Qu Wenruo   btrfs: qgroup: Ma...
2804
2805
  static int qgroup_reserve(struct btrfs_root *root, u64 num_bytes, bool enforce,
  			  enum btrfs_qgroup_rsv_type type)
bed92eae2   Arne Jansen   Btrfs: qgroup imp...
2806
  {
bed92eae2   Arne Jansen   Btrfs: qgroup imp...
2807
2808
2809
2810
  	struct btrfs_qgroup *qgroup;
  	struct btrfs_fs_info *fs_info = root->fs_info;
  	u64 ref_root = root->root_key.objectid;
  	int ret = 0;
bed92eae2   Arne Jansen   Btrfs: qgroup imp...
2811
2812
2813
2814
2815
2816
2817
2818
  	struct ulist_node *unode;
  	struct ulist_iterator uiter;
  
  	if (!is_fstree(ref_root))
  		return 0;
  
  	if (num_bytes == 0)
  		return 0;
f29efe292   Sargun Dhillon   btrfs: add quota ...
2819
2820
2821
2822
  
  	if (test_bit(BTRFS_FS_QUOTA_OVERRIDE, &fs_info->flags) &&
  	    capable(CAP_SYS_RESOURCE))
  		enforce = false;
bed92eae2   Arne Jansen   Btrfs: qgroup imp...
2823
  	spin_lock(&fs_info->qgroup_lock);
e3b0edd29   Marcos Paulo de Souza   btrfs: qgroup: re...
2824
  	if (!fs_info->quota_root)
bed92eae2   Arne Jansen   Btrfs: qgroup imp...
2825
2826
2827
2828
2829
2830
2831
2832
2833
2834
  		goto out;
  
  	qgroup = find_qgroup_rb(fs_info, ref_root);
  	if (!qgroup)
  		goto out;
  
  	/*
  	 * in a first step, we check all affected qgroups if any limits would
  	 * be exceeded
  	 */
1e8f91586   Wang Shilong   Btrfs: introduce ...
2835
2836
  	ulist_reinit(fs_info->qgroup_ulist);
  	ret = ulist_add(fs_info->qgroup_ulist, qgroup->qgroupid,
a1840b502   David Sterba   btrfs: use helper...
2837
  			qgroup_to_aux(qgroup), GFP_ATOMIC);
3c97185c6   Wang Shilong   Btrfs: fix missin...
2838
2839
  	if (ret < 0)
  		goto out;
bed92eae2   Arne Jansen   Btrfs: qgroup imp...
2840
  	ULIST_ITER_INIT(&uiter);
1e8f91586   Wang Shilong   Btrfs: introduce ...
2841
  	while ((unode = ulist_next(fs_info->qgroup_ulist, &uiter))) {
bed92eae2   Arne Jansen   Btrfs: qgroup imp...
2842
2843
  		struct btrfs_qgroup *qg;
  		struct btrfs_qgroup_list *glist;
ef2fff64f   David Sterba   btrfs: rename hel...
2844
  		qg = unode_aux_to_qgroup(unode);
bed92eae2   Arne Jansen   Btrfs: qgroup imp...
2845

adca4d945   Qu Wenruo   btrfs: qgroup: re...
2846
  		if (enforce && !qgroup_check_limits(qg, num_bytes)) {
bed92eae2   Arne Jansen   Btrfs: qgroup imp...
2847
  			ret = -EDQUOT;
720f1e206   Wang Shilong   Btrfs: return as ...
2848
2849
  			goto out;
  		}
bed92eae2   Arne Jansen   Btrfs: qgroup imp...
2850
2851
  
  		list_for_each_entry(glist, &qg->groups, next_group) {
1e8f91586   Wang Shilong   Btrfs: introduce ...
2852
2853
  			ret = ulist_add(fs_info->qgroup_ulist,
  					glist->group->qgroupid,
a1840b502   David Sterba   btrfs: use helper...
2854
  					qgroup_to_aux(glist->group), GFP_ATOMIC);
3c97185c6   Wang Shilong   Btrfs: fix missin...
2855
2856
  			if (ret < 0)
  				goto out;
bed92eae2   Arne Jansen   Btrfs: qgroup imp...
2857
2858
  		}
  	}
3c97185c6   Wang Shilong   Btrfs: fix missin...
2859
  	ret = 0;
bed92eae2   Arne Jansen   Btrfs: qgroup imp...
2860
2861
2862
2863
  	/*
  	 * no limits exceeded, now record the reservation into all qgroups
  	 */
  	ULIST_ITER_INIT(&uiter);
1e8f91586   Wang Shilong   Btrfs: introduce ...
2864
  	while ((unode = ulist_next(fs_info->qgroup_ulist, &uiter))) {
bed92eae2   Arne Jansen   Btrfs: qgroup imp...
2865
  		struct btrfs_qgroup *qg;
ef2fff64f   David Sterba   btrfs: rename hel...
2866
  		qg = unode_aux_to_qgroup(unode);
bed92eae2   Arne Jansen   Btrfs: qgroup imp...
2867

64ee4e751   Qu Wenruo   btrfs: qgroup: Up...
2868
  		qgroup_rsv_add(fs_info, qg, num_bytes, type);
bed92eae2   Arne Jansen   Btrfs: qgroup imp...
2869
2870
2871
2872
  	}
  
  out:
  	spin_unlock(&fs_info->qgroup_lock);
bed92eae2   Arne Jansen   Btrfs: qgroup imp...
2873
2874
  	return ret;
  }
e1211d0e8   Qu Wenruo   btrfs: qgroup: Do...
2875
2876
2877
2878
2879
2880
2881
2882
2883
  /*
   * Free @num_bytes of reserved space with @type for qgroup.  (Normally level 0
   * qgroup).
   *
   * Will handle all higher level qgroup too.
   *
   * NOTE: If @num_bytes is (u64)-1, this means to free all bytes of this qgroup.
   * This special case is only used for META_PERTRANS type.
   */
297d750b9   Qu Wenruo   btrfs: delayed_re...
2884
  void btrfs_qgroup_free_refroot(struct btrfs_fs_info *fs_info,
d4e5c9205   Qu Wenruo   btrfs: qgroup: Sk...
2885
2886
  			       u64 ref_root, u64 num_bytes,
  			       enum btrfs_qgroup_rsv_type type)
bed92eae2   Arne Jansen   Btrfs: qgroup imp...
2887
  {
bed92eae2   Arne Jansen   Btrfs: qgroup imp...
2888
  	struct btrfs_qgroup *qgroup;
bed92eae2   Arne Jansen   Btrfs: qgroup imp...
2889
2890
  	struct ulist_node *unode;
  	struct ulist_iterator uiter;
3c97185c6   Wang Shilong   Btrfs: fix missin...
2891
  	int ret = 0;
bed92eae2   Arne Jansen   Btrfs: qgroup imp...
2892
2893
2894
2895
2896
2897
  
  	if (!is_fstree(ref_root))
  		return;
  
  	if (num_bytes == 0)
  		return;
e1211d0e8   Qu Wenruo   btrfs: qgroup: Do...
2898
2899
2900
2901
  	if (num_bytes == (u64)-1 && type != BTRFS_QGROUP_RSV_META_PERTRANS) {
  		WARN(1, "%s: Invalid type to free", __func__);
  		return;
  	}
bed92eae2   Arne Jansen   Btrfs: qgroup imp...
2902
  	spin_lock(&fs_info->qgroup_lock);
e3b0edd29   Marcos Paulo de Souza   btrfs: qgroup: re...
2903
  	if (!fs_info->quota_root)
bed92eae2   Arne Jansen   Btrfs: qgroup imp...
2904
2905
2906
2907
2908
  		goto out;
  
  	qgroup = find_qgroup_rb(fs_info, ref_root);
  	if (!qgroup)
  		goto out;
e1211d0e8   Qu Wenruo   btrfs: qgroup: Do...
2909
  	if (num_bytes == (u64)-1)
8287475a2   Qu Wenruo   btrfs: qgroup: Us...
2910
2911
2912
2913
  		/*
  		 * We're freeing all pertrans rsv, get reserved value from
  		 * level 0 qgroup as real num_bytes to free.
  		 */
e1211d0e8   Qu Wenruo   btrfs: qgroup: Do...
2914
  		num_bytes = qgroup->rsv.values[type];
1e8f91586   Wang Shilong   Btrfs: introduce ...
2915
2916
  	ulist_reinit(fs_info->qgroup_ulist);
  	ret = ulist_add(fs_info->qgroup_ulist, qgroup->qgroupid,
a1840b502   David Sterba   btrfs: use helper...
2917
  			qgroup_to_aux(qgroup), GFP_ATOMIC);
3c97185c6   Wang Shilong   Btrfs: fix missin...
2918
2919
  	if (ret < 0)
  		goto out;
bed92eae2   Arne Jansen   Btrfs: qgroup imp...
2920
  	ULIST_ITER_INIT(&uiter);
1e8f91586   Wang Shilong   Btrfs: introduce ...
2921
  	while ((unode = ulist_next(fs_info->qgroup_ulist, &uiter))) {
bed92eae2   Arne Jansen   Btrfs: qgroup imp...
2922
2923
  		struct btrfs_qgroup *qg;
  		struct btrfs_qgroup_list *glist;
ef2fff64f   David Sterba   btrfs: rename hel...
2924
  		qg = unode_aux_to_qgroup(unode);
bed92eae2   Arne Jansen   Btrfs: qgroup imp...
2925

64ee4e751   Qu Wenruo   btrfs: qgroup: Up...
2926
  		qgroup_rsv_release(fs_info, qg, num_bytes, type);
bed92eae2   Arne Jansen   Btrfs: qgroup imp...
2927
2928
  
  		list_for_each_entry(glist, &qg->groups, next_group) {
1e8f91586   Wang Shilong   Btrfs: introduce ...
2929
2930
  			ret = ulist_add(fs_info->qgroup_ulist,
  					glist->group->qgroupid,
a1840b502   David Sterba   btrfs: use helper...
2931
  					qgroup_to_aux(glist->group), GFP_ATOMIC);
3c97185c6   Wang Shilong   Btrfs: fix missin...
2932
2933
  			if (ret < 0)
  				goto out;
bed92eae2   Arne Jansen   Btrfs: qgroup imp...
2934
2935
2936
2937
2938
  		}
  	}
  
  out:
  	spin_unlock(&fs_info->qgroup_lock);
bed92eae2   Arne Jansen   Btrfs: qgroup imp...
2939
  }
2f2320360   Jan Schmidt   Btrfs: rescan for...
2940
  /*
ff3d27a04   Qu Wenruo   btrfs: qgroup: Fi...
2941
2942
2943
2944
2945
2946
2947
2948
2949
2950
2951
2952
2953
2954
2955
   * Check if the leaf is the last leaf. Which means all node pointers
   * are at their last position.
   */
  static bool is_last_leaf(struct btrfs_path *path)
  {
  	int i;
  
  	for (i = 1; i < BTRFS_MAX_LEVEL && path->nodes[i]; i++) {
  		if (path->slots[i] != btrfs_header_nritems(path->nodes[i]) - 1)
  			return false;
  	}
  	return true;
  }
  
  /*
2f2320360   Jan Schmidt   Btrfs: rescan for...
2956
   * returns < 0 on error, 0 when more leafs are to be scanned.
3393168d2   Qu Wenruo   btrfs: qgroup: Fi...
2957
   * returns 1 when done.
2f2320360   Jan Schmidt   Btrfs: rescan for...
2958
   */
62088ca74   Lu Fengqi   btrfs: qgroup: Dr...
2959
2960
  static int qgroup_rescan_leaf(struct btrfs_trans_handle *trans,
  			      struct btrfs_path *path)
2f2320360   Jan Schmidt   Btrfs: rescan for...
2961
  {
62088ca74   Lu Fengqi   btrfs: qgroup: Dr...
2962
  	struct btrfs_fs_info *fs_info = trans->fs_info;
2f2320360   Jan Schmidt   Btrfs: rescan for...
2963
  	struct btrfs_key found;
0a0e8b893   Qu Wenruo   btrfs: qgroup: Do...
2964
  	struct extent_buffer *scratch_leaf = NULL;
2f2320360   Jan Schmidt   Btrfs: rescan for...
2965
  	struct ulist *roots = NULL;
fcebe4562   Josef Bacik   Btrfs: rework qgr...
2966
  	u64 num_bytes;
ff3d27a04   Qu Wenruo   btrfs: qgroup: Fi...
2967
  	bool done;
2f2320360   Jan Schmidt   Btrfs: rescan for...
2968
2969
  	int slot;
  	int ret;
2f2320360   Jan Schmidt   Btrfs: rescan for...
2970
2971
2972
2973
  	mutex_lock(&fs_info->qgroup_rescan_lock);
  	ret = btrfs_search_slot_for_read(fs_info->extent_root,
  					 &fs_info->qgroup_rescan_progress,
  					 path, 1, 0);
ab8d0fc48   Jeff Mahoney   btrfs: convert pr...
2974
2975
2976
2977
2978
  	btrfs_debug(fs_info,
  		"current progress key (%llu %u %llu), search_slot ret %d",
  		fs_info->qgroup_rescan_progress.objectid,
  		fs_info->qgroup_rescan_progress.type,
  		fs_info->qgroup_rescan_progress.offset, ret);
2f2320360   Jan Schmidt   Btrfs: rescan for...
2979
2980
2981
2982
2983
2984
2985
2986
2987
2988
2989
2990
2991
2992
2993
  
  	if (ret) {
  		/*
  		 * The rescan is about to end, we will not be scanning any
  		 * further blocks. We cannot unset the RESCAN flag here, because
  		 * we want to commit the transaction if everything went well.
  		 * To make the live accounting work in this phase, we set our
  		 * scan progress pointer such that every real extent objectid
  		 * will be smaller.
  		 */
  		fs_info->qgroup_rescan_progress.objectid = (u64)-1;
  		btrfs_release_path(path);
  		mutex_unlock(&fs_info->qgroup_rescan_lock);
  		return ret;
  	}
ff3d27a04   Qu Wenruo   btrfs: qgroup: Fi...
2994
  	done = is_last_leaf(path);
2f2320360   Jan Schmidt   Btrfs: rescan for...
2995
2996
2997
2998
  
  	btrfs_item_key_to_cpu(path->nodes[0], &found,
  			      btrfs_header_nritems(path->nodes[0]) - 1);
  	fs_info->qgroup_rescan_progress.objectid = found.objectid + 1;
0a0e8b893   Qu Wenruo   btrfs: qgroup: Do...
2999
3000
3001
3002
3003
3004
  	scratch_leaf = btrfs_clone_extent_buffer(path->nodes[0]);
  	if (!scratch_leaf) {
  		ret = -ENOMEM;
  		mutex_unlock(&fs_info->qgroup_rescan_lock);
  		goto out;
  	}
2f2320360   Jan Schmidt   Btrfs: rescan for...
3005
3006
3007
3008
3009
3010
  	slot = path->slots[0];
  	btrfs_release_path(path);
  	mutex_unlock(&fs_info->qgroup_rescan_lock);
  
  	for (; slot < btrfs_header_nritems(scratch_leaf); ++slot) {
  		btrfs_item_key_to_cpu(scratch_leaf, &found, slot);
3a6d75e84   Josef Bacik   Btrfs: fix qgroup...
3011
3012
  		if (found.type != BTRFS_EXTENT_ITEM_KEY &&
  		    found.type != BTRFS_METADATA_ITEM_KEY)
2f2320360   Jan Schmidt   Btrfs: rescan for...
3013
  			continue;
3a6d75e84   Josef Bacik   Btrfs: fix qgroup...
3014
  		if (found.type == BTRFS_METADATA_ITEM_KEY)
da17066c4   Jeff Mahoney   btrfs: pull node/...
3015
  			num_bytes = fs_info->nodesize;
3a6d75e84   Josef Bacik   Btrfs: fix qgroup...
3016
3017
  		else
  			num_bytes = found.offset;
fcebe4562   Josef Bacik   Btrfs: rework qgr...
3018
  		ret = btrfs_find_all_roots(NULL, fs_info, found.objectid, 0,
c995ab3cd   Zygo Blaxell   btrfs: add a flag...
3019
  					   &roots, false);
2f2320360   Jan Schmidt   Btrfs: rescan for...
3020
3021
  		if (ret < 0)
  			goto out;
9d220c95f   Qu Wenruo   btrfs: qgroup: Sw...
3022
  		/* For rescan, just pass old_roots as NULL */
8696d7604   Lu Fengqi   btrfs: qgroup: Dr...
3023
3024
  		ret = btrfs_qgroup_account_extent(trans, found.objectid,
  						  num_bytes, NULL, roots);
9d220c95f   Qu Wenruo   btrfs: qgroup: Sw...
3025
  		if (ret < 0)
fcebe4562   Josef Bacik   Btrfs: rework qgr...
3026
  			goto out;
2f2320360   Jan Schmidt   Btrfs: rescan for...
3027
  	}
2f2320360   Jan Schmidt   Btrfs: rescan for...
3028
  out:
df4497146   Nikolay Borisov   btrfs: Remove unn...
3029
  	if (scratch_leaf)
0a0e8b893   Qu Wenruo   btrfs: qgroup: Do...
3030
  		free_extent_buffer(scratch_leaf);
2f2320360   Jan Schmidt   Btrfs: rescan for...
3031

6f7de19ed   Qu Wenruo   btrfs: quota: Set...
3032
  	if (done && !ret) {
ff3d27a04   Qu Wenruo   btrfs: qgroup: Fi...
3033
  		ret = 1;
6f7de19ed   Qu Wenruo   btrfs: quota: Set...
3034
3035
  		fs_info->qgroup_rescan_progress.objectid = (u64)-1;
  	}
2f2320360   Jan Schmidt   Btrfs: rescan for...
3036
3037
  	return ret;
  }
d458b0540   Qu Wenruo   btrfs: Cleanup th...
3038
  static void btrfs_qgroup_rescan_worker(struct btrfs_work *work)
2f2320360   Jan Schmidt   Btrfs: rescan for...
3039
  {
b382a324b   Jan Schmidt   Btrfs: fix qgroup...
3040
3041
  	struct btrfs_fs_info *fs_info = container_of(work, struct btrfs_fs_info,
  						     qgroup_rescan_work);
2f2320360   Jan Schmidt   Btrfs: rescan for...
3042
3043
  	struct btrfs_path *path;
  	struct btrfs_trans_handle *trans = NULL;
2f2320360   Jan Schmidt   Btrfs: rescan for...
3044
  	int err = -ENOMEM;
53b7cde9d   Qu Wenruo   btrfs: Update btr...
3045
  	int ret = 0;
2f2320360   Jan Schmidt   Btrfs: rescan for...
3046
3047
3048
3049
  
  	path = btrfs_alloc_path();
  	if (!path)
  		goto out;
b6debf15d   Qu Wenruo   btrfs: qgroup: Se...
3050
3051
3052
3053
3054
3055
  	/*
  	 * Rescan should only search for commit root, and any later difference
  	 * should be recorded by qgroup
  	 */
  	path->search_commit_root = 1;
  	path->skip_locking = 1;
2f2320360   Jan Schmidt   Btrfs: rescan for...
3056
3057
  
  	err = 0;
7343dd61f   Justin Maggard   btrfs: qgroup: ex...
3058
  	while (!err && !btrfs_fs_closing(fs_info)) {
2f2320360   Jan Schmidt   Btrfs: rescan for...
3059
3060
3061
3062
3063
  		trans = btrfs_start_transaction(fs_info->fs_root, 0);
  		if (IS_ERR(trans)) {
  			err = PTR_ERR(trans);
  			break;
  		}
afcdd129e   Josef Bacik   Btrfs: add a flag...
3064
  		if (!test_bit(BTRFS_FS_QUOTA_ENABLED, &fs_info->flags)) {
2f2320360   Jan Schmidt   Btrfs: rescan for...
3065
3066
  			err = -EINTR;
  		} else {
62088ca74   Lu Fengqi   btrfs: qgroup: Dr...
3067
  			err = qgroup_rescan_leaf(trans, path);
2f2320360   Jan Schmidt   Btrfs: rescan for...
3068
3069
  		}
  		if (err > 0)
3a45bb207   Jeff Mahoney   btrfs: remove roo...
3070
  			btrfs_commit_transaction(trans);
2f2320360   Jan Schmidt   Btrfs: rescan for...
3071
  		else
3a45bb207   Jeff Mahoney   btrfs: remove roo...
3072
  			btrfs_end_transaction(trans);
2f2320360   Jan Schmidt   Btrfs: rescan for...
3073
3074
3075
  	}
  
  out:
2f2320360   Jan Schmidt   Btrfs: rescan for...
3076
  	btrfs_free_path(path);
2f2320360   Jan Schmidt   Btrfs: rescan for...
3077
3078
  
  	mutex_lock(&fs_info->qgroup_rescan_lock);
3393168d2   Qu Wenruo   btrfs: qgroup: Fi...
3079
  	if (err > 0 &&
2f2320360   Jan Schmidt   Btrfs: rescan for...
3080
3081
3082
3083
3084
3085
  	    fs_info->qgroup_flags & BTRFS_QGROUP_STATUS_FLAG_INCONSISTENT) {
  		fs_info->qgroup_flags &= ~BTRFS_QGROUP_STATUS_FLAG_INCONSISTENT;
  	} else if (err < 0) {
  		fs_info->qgroup_flags |= BTRFS_QGROUP_STATUS_FLAG_INCONSISTENT;
  	}
  	mutex_unlock(&fs_info->qgroup_rescan_lock);
53b7cde9d   Qu Wenruo   btrfs: Update btr...
3086
  	/*
013276101   Nicholas D Steeves   btrfs: fix string...
3087
  	 * only update status, since the previous part has already updated the
53b7cde9d   Qu Wenruo   btrfs: Update btr...
3088
3089
3090
3091
3092
  	 * qgroup info.
  	 */
  	trans = btrfs_start_transaction(fs_info->quota_root, 1);
  	if (IS_ERR(trans)) {
  		err = PTR_ERR(trans);
13fc1d271   Filipe Manana   Btrfs: fix race s...
3093
  		trans = NULL;
53b7cde9d   Qu Wenruo   btrfs: Update btr...
3094
  		btrfs_err(fs_info,
913e15357   David Sterba   btrfs: drop newli...
3095
  			  "fail to start transaction for status update: %d",
53b7cde9d   Qu Wenruo   btrfs: Update btr...
3096
  			  err);
53b7cde9d   Qu Wenruo   btrfs: Update btr...
3097
  	}
13fc1d271   Filipe Manana   Btrfs: fix race s...
3098
3099
3100
3101
3102
3103
3104
3105
3106
3107
3108
  
  	mutex_lock(&fs_info->qgroup_rescan_lock);
  	if (!btrfs_fs_closing(fs_info))
  		fs_info->qgroup_flags &= ~BTRFS_QGROUP_STATUS_FLAG_RESCAN;
  	if (trans) {
  		ret = update_qgroup_status_item(trans);
  		if (ret < 0) {
  			err = ret;
  			btrfs_err(fs_info, "fail to update qgroup status: %d",
  				  err);
  		}
53b7cde9d   Qu Wenruo   btrfs: Update btr...
3109
  	}
13fc1d271   Filipe Manana   Btrfs: fix race s...
3110
3111
3112
3113
3114
3115
  	fs_info->qgroup_rescan_running = false;
  	complete_all(&fs_info->qgroup_rescan_completion);
  	mutex_unlock(&fs_info->qgroup_rescan_lock);
  
  	if (!trans)
  		return;
3a45bb207   Jeff Mahoney   btrfs: remove roo...
3116
  	btrfs_end_transaction(trans);
53b7cde9d   Qu Wenruo   btrfs: Update btr...
3117

7343dd61f   Justin Maggard   btrfs: qgroup: ex...
3118
3119
3120
  	if (btrfs_fs_closing(fs_info)) {
  		btrfs_info(fs_info, "qgroup scan paused");
  	} else if (err >= 0) {
efe120a06   Frank Holton   Btrfs: convert pr...
3121
  		btrfs_info(fs_info, "qgroup scan completed%s",
3393168d2   Qu Wenruo   btrfs: qgroup: Fi...
3122
  			err > 0 ? " (inconsistency flag cleared)" : "");
2f2320360   Jan Schmidt   Btrfs: rescan for...
3123
  	} else {
efe120a06   Frank Holton   Btrfs: convert pr...
3124
  		btrfs_err(fs_info, "qgroup scan failed with %d", err);
2f2320360   Jan Schmidt   Btrfs: rescan for...
3125
3126
  	}
  }
b382a324b   Jan Schmidt   Btrfs: fix qgroup...
3127
3128
3129
3130
3131
3132
3133
  /*
   * Checks that (a) no rescan is running and (b) quota is enabled. Allocates all
   * memory required for the rescan context.
   */
  static int
  qgroup_rescan_init(struct btrfs_fs_info *fs_info, u64 progress_objectid,
  		   int init_flags)
2f2320360   Jan Schmidt   Btrfs: rescan for...
3134
3135
  {
  	int ret = 0;
2f2320360   Jan Schmidt   Btrfs: rescan for...
3136

9593bf496   Qu Wenruo   btrfs: qgroup: sh...
3137
3138
  	if (!init_flags) {
  		/* we're resuming qgroup rescan at mount time */
e4e7ede73   Filipe Manana   Btrfs: fix mount ...
3139
3140
  		if (!(fs_info->qgroup_flags &
  		      BTRFS_QGROUP_STATUS_FLAG_RESCAN)) {
9593bf496   Qu Wenruo   btrfs: qgroup: sh...
3141
  			btrfs_warn(fs_info,
37d02592f   Nikolay Borisov   btrfs: Fix error ...
3142
  			"qgroup rescan init failed, qgroup rescan is not queued");
e4e7ede73   Filipe Manana   Btrfs: fix mount ...
3143
3144
3145
  			ret = -EINVAL;
  		} else if (!(fs_info->qgroup_flags &
  			     BTRFS_QGROUP_STATUS_FLAG_ON)) {
9593bf496   Qu Wenruo   btrfs: qgroup: sh...
3146
  			btrfs_warn(fs_info,
37d02592f   Nikolay Borisov   btrfs: Fix error ...
3147
  			"qgroup rescan init failed, qgroup is not enabled");
e4e7ede73   Filipe Manana   Btrfs: fix mount ...
3148
3149
3150
3151
3152
  			ret = -EINVAL;
  		}
  
  		if (ret)
  			return ret;
b382a324b   Jan Schmidt   Btrfs: fix qgroup...
3153
  	}
2f2320360   Jan Schmidt   Btrfs: rescan for...
3154
3155
  
  	mutex_lock(&fs_info->qgroup_rescan_lock);
b382a324b   Jan Schmidt   Btrfs: fix qgroup...
3156
3157
  
  	if (init_flags) {
9593bf496   Qu Wenruo   btrfs: qgroup: sh...
3158
3159
3160
  		if (fs_info->qgroup_flags & BTRFS_QGROUP_STATUS_FLAG_RESCAN) {
  			btrfs_warn(fs_info,
  				   "qgroup rescan is already in progress");
b382a324b   Jan Schmidt   Btrfs: fix qgroup...
3161
  			ret = -EINPROGRESS;
9593bf496   Qu Wenruo   btrfs: qgroup: sh...
3162
3163
3164
3165
  		} else if (!(fs_info->qgroup_flags &
  			     BTRFS_QGROUP_STATUS_FLAG_ON)) {
  			btrfs_warn(fs_info,
  			"qgroup rescan init failed, qgroup is not enabled");
b382a324b   Jan Schmidt   Btrfs: fix qgroup...
3166
  			ret = -EINVAL;
9593bf496   Qu Wenruo   btrfs: qgroup: sh...
3167
  		}
b382a324b   Jan Schmidt   Btrfs: fix qgroup...
3168
3169
  
  		if (ret) {
b382a324b   Jan Schmidt   Btrfs: fix qgroup...
3170
  			mutex_unlock(&fs_info->qgroup_rescan_lock);
9593bf496   Qu Wenruo   btrfs: qgroup: sh...
3171
  			return ret;
b382a324b   Jan Schmidt   Btrfs: fix qgroup...
3172
  		}
b382a324b   Jan Schmidt   Btrfs: fix qgroup...
3173
  		fs_info->qgroup_flags |= BTRFS_QGROUP_STATUS_FLAG_RESCAN;
2f2320360   Jan Schmidt   Btrfs: rescan for...
3174
  	}
2f2320360   Jan Schmidt   Btrfs: rescan for...
3175
3176
  	memset(&fs_info->qgroup_rescan_progress, 0,
  		sizeof(fs_info->qgroup_rescan_progress));
b382a324b   Jan Schmidt   Btrfs: fix qgroup...
3177
  	fs_info->qgroup_rescan_progress.objectid = progress_objectid;
190631f1c   Filipe Manana   Btrfs: fix race w...
3178
  	init_completion(&fs_info->qgroup_rescan_completion);
b382a324b   Jan Schmidt   Btrfs: fix qgroup...
3179
  	mutex_unlock(&fs_info->qgroup_rescan_lock);
fc97fab0e   Qu Wenruo   btrfs: Replace fs...
3180
3181
  	btrfs_init_work(&fs_info->qgroup_rescan_work,
  			btrfs_qgroup_rescan_worker, NULL, NULL);
b382a324b   Jan Schmidt   Btrfs: fix qgroup...
3182
3183
3184
3185
3186
3187
3188
3189
3190
3191
  	return 0;
  }
  
  static void
  qgroup_rescan_zero_tracking(struct btrfs_fs_info *fs_info)
  {
  	struct rb_node *n;
  	struct btrfs_qgroup *qgroup;
  
  	spin_lock(&fs_info->qgroup_lock);
2f2320360   Jan Schmidt   Btrfs: rescan for...
3192
3193
3194
3195
3196
3197
3198
  	/* clear all current qgroup tracking information */
  	for (n = rb_first(&fs_info->qgroup_tree); n; n = rb_next(n)) {
  		qgroup = rb_entry(n, struct btrfs_qgroup, node);
  		qgroup->rfer = 0;
  		qgroup->rfer_cmpr = 0;
  		qgroup->excl = 0;
  		qgroup->excl_cmpr = 0;
9c7b0c2e8   Qu Wenruo   btrfs: qgroup: Di...
3199
  		qgroup_dirty(fs_info, qgroup);
2f2320360   Jan Schmidt   Btrfs: rescan for...
3200
3201
  	}
  	spin_unlock(&fs_info->qgroup_lock);
b382a324b   Jan Schmidt   Btrfs: fix qgroup...
3202
  }
2f2320360   Jan Schmidt   Btrfs: rescan for...
3203

b382a324b   Jan Schmidt   Btrfs: fix qgroup...
3204
3205
3206
3207
3208
3209
3210
3211
3212
3213
3214
3215
3216
3217
3218
3219
3220
3221
3222
3223
3224
3225
3226
3227
3228
3229
  int
  btrfs_qgroup_rescan(struct btrfs_fs_info *fs_info)
  {
  	int ret = 0;
  	struct btrfs_trans_handle *trans;
  
  	ret = qgroup_rescan_init(fs_info, 0, 1);
  	if (ret)
  		return ret;
  
  	/*
  	 * We have set the rescan_progress to 0, which means no more
  	 * delayed refs will be accounted by btrfs_qgroup_account_ref.
  	 * However, btrfs_qgroup_account_ref may be right after its call
  	 * to btrfs_find_all_roots, in which case it would still do the
  	 * accounting.
  	 * To solve this, we're committing the transaction, which will
  	 * ensure we run all delayed refs and only after that, we are
  	 * going to clear all tracking information for a clean start.
  	 */
  
  	trans = btrfs_join_transaction(fs_info->fs_root);
  	if (IS_ERR(trans)) {
  		fs_info->qgroup_flags &= ~BTRFS_QGROUP_STATUS_FLAG_RESCAN;
  		return PTR_ERR(trans);
  	}
3a45bb207   Jeff Mahoney   btrfs: remove roo...
3230
  	ret = btrfs_commit_transaction(trans);
b382a324b   Jan Schmidt   Btrfs: fix qgroup...
3231
3232
3233
3234
3235
3236
  	if (ret) {
  		fs_info->qgroup_flags &= ~BTRFS_QGROUP_STATUS_FLAG_RESCAN;
  		return ret;
  	}
  
  	qgroup_rescan_zero_tracking(fs_info);
d61acbbf5   Qu Wenruo   btrfs: qgroup: en...
3237
3238
  	mutex_lock(&fs_info->qgroup_rescan_lock);
  	fs_info->qgroup_rescan_running = true;
fc97fab0e   Qu Wenruo   btrfs: Replace fs...
3239
3240
  	btrfs_queue_work(fs_info->qgroup_rescan_workers,
  			 &fs_info->qgroup_rescan_work);
d61acbbf5   Qu Wenruo   btrfs: qgroup: en...
3241
  	mutex_unlock(&fs_info->qgroup_rescan_lock);
2f2320360   Jan Schmidt   Btrfs: rescan for...
3242
3243
3244
  
  	return 0;
  }
57254b6eb   Jan Schmidt   Btrfs: add ioctl ...
3245

d06f23d6a   Jeff Mahoney   btrfs: waiting on...
3246
3247
  int btrfs_qgroup_wait_for_completion(struct btrfs_fs_info *fs_info,
  				     bool interruptible)
57254b6eb   Jan Schmidt   Btrfs: add ioctl ...
3248
3249
3250
3251
3252
  {
  	int running;
  	int ret = 0;
  
  	mutex_lock(&fs_info->qgroup_rescan_lock);
d2c609b83   Jeff Mahoney   btrfs: properly t...
3253
  	running = fs_info->qgroup_rescan_running;
57254b6eb   Jan Schmidt   Btrfs: add ioctl ...
3254
  	mutex_unlock(&fs_info->qgroup_rescan_lock);
d06f23d6a   Jeff Mahoney   btrfs: waiting on...
3255
3256
3257
3258
  	if (!running)
  		return 0;
  
  	if (interruptible)
57254b6eb   Jan Schmidt   Btrfs: add ioctl ...
3259
3260
  		ret = wait_for_completion_interruptible(
  					&fs_info->qgroup_rescan_completion);
d06f23d6a   Jeff Mahoney   btrfs: waiting on...
3261
3262
  	else
  		wait_for_completion(&fs_info->qgroup_rescan_completion);
57254b6eb   Jan Schmidt   Btrfs: add ioctl ...
3263
3264
3265
  
  	return ret;
  }
b382a324b   Jan Schmidt   Btrfs: fix qgroup...
3266
3267
3268
3269
3270
3271
3272
3273
  
  /*
   * this is only called from open_ctree where we're still single threaded, thus
   * locking is omitted here.
   */
  void
  btrfs_qgroup_rescan_resume(struct btrfs_fs_info *fs_info)
  {
d61acbbf5   Qu Wenruo   btrfs: qgroup: en...
3274
3275
3276
  	if (fs_info->qgroup_flags & BTRFS_QGROUP_STATUS_FLAG_RESCAN) {
  		mutex_lock(&fs_info->qgroup_rescan_lock);
  		fs_info->qgroup_rescan_running = true;
fc97fab0e   Qu Wenruo   btrfs: Replace fs...
3277
3278
  		btrfs_queue_work(fs_info->qgroup_rescan_workers,
  				 &fs_info->qgroup_rescan_work);
d61acbbf5   Qu Wenruo   btrfs: qgroup: en...
3279
3280
  		mutex_unlock(&fs_info->qgroup_rescan_lock);
  	}
b382a324b   Jan Schmidt   Btrfs: fix qgroup...
3281
  }
524725537   Qu Wenruo   btrfs: qgroup: In...
3282

263da812e   Qu Wenruo   btrfs: qgroup: al...
3283
3284
3285
3286
3287
3288
3289
3290
3291
3292
3293
3294
3295
3296
3297
3298
3299
3300
3301
3302
3303
3304
3305
3306
3307
3308
3309
3310
3311
3312
3313
3314
3315
3316
3317
3318
3319
3320
3321
3322
3323
3324
3325
3326
3327
3328
3329
3330
3331
3332
3333
3334
3335
3336
3337
3338
3339
3340
3341
3342
3343
3344
3345
3346
3347
3348
  #define rbtree_iterate_from_safe(node, next, start)				\
         for (node = start; node && ({ next = rb_next(node); 1;}); node = next)
  
  static int qgroup_unreserve_range(struct btrfs_inode *inode,
  				  struct extent_changeset *reserved, u64 start,
  				  u64 len)
  {
  	struct rb_node *node;
  	struct rb_node *next;
  	struct ulist_node *entry = NULL;
  	int ret = 0;
  
  	node = reserved->range_changed.root.rb_node;
  	while (node) {
  		entry = rb_entry(node, struct ulist_node, rb_node);
  		if (entry->val < start)
  			node = node->rb_right;
  		else if (entry)
  			node = node->rb_left;
  		else
  			break;
  	}
  
  	/* Empty changeset */
  	if (!entry)
  		return 0;
  
  	if (entry->val > start && rb_prev(&entry->rb_node))
  		entry = rb_entry(rb_prev(&entry->rb_node), struct ulist_node,
  				 rb_node);
  
  	rbtree_iterate_from_safe(node, next, &entry->rb_node) {
  		u64 entry_start;
  		u64 entry_end;
  		u64 entry_len;
  		int clear_ret;
  
  		entry = rb_entry(node, struct ulist_node, rb_node);
  		entry_start = entry->val;
  		entry_end = entry->aux;
  		entry_len = entry_end - entry_start + 1;
  
  		if (entry_start >= start + len)
  			break;
  		if (entry_start + entry_len <= start)
  			continue;
  		/*
  		 * Now the entry is in [start, start + len), revert the
  		 * EXTENT_QGROUP_RESERVED bit.
  		 */
  		clear_ret = clear_extent_bits(&inode->io_tree, entry_start,
  					      entry_end, EXTENT_QGROUP_RESERVED);
  		if (!ret && clear_ret < 0)
  			ret = clear_ret;
  
  		ulist_del(&reserved->range_changed, entry->val, entry->aux);
  		if (likely(reserved->bytes_changed >= entry_len)) {
  			reserved->bytes_changed -= entry_len;
  		} else {
  			WARN_ON(1);
  			reserved->bytes_changed = 0;
  		}
  	}
  
  	return ret;
  }
524725537   Qu Wenruo   btrfs: qgroup: In...
3349
  /*
c53e96536   Qu Wenruo   btrfs: qgroup: tr...
3350
   * Try to free some space for qgroup.
524725537   Qu Wenruo   btrfs: qgroup: In...
3351
   *
c53e96536   Qu Wenruo   btrfs: qgroup: tr...
3352
3353
3354
3355
3356
   * For qgroup, there are only 3 ways to free qgroup space:
   * - Flush nodatacow write
   *   Any nodatacow write will free its reserved data space at run_delalloc_range().
   *   In theory, we should only flush nodatacow inodes, but it's not yet
   *   possible, so we need to flush the whole root.
524725537   Qu Wenruo   btrfs: qgroup: In...
3357
   *
c53e96536   Qu Wenruo   btrfs: qgroup: tr...
3358
3359
3360
3361
   * - Wait for ordered extents
   *   When ordered extents are finished, their reserved metadata is finally
   *   converted to per_trans status, which can be freed by later commit
   *   transaction.
524725537   Qu Wenruo   btrfs: qgroup: In...
3362
   *
c53e96536   Qu Wenruo   btrfs: qgroup: tr...
3363
3364
3365
3366
   * - Commit transaction
   *   This would free the meta_per_trans space.
   *   In theory this shouldn't provide much space, but any more qgroup space
   *   is needed.
524725537   Qu Wenruo   btrfs: qgroup: In...
3367
   */
c53e96536   Qu Wenruo   btrfs: qgroup: tr...
3368
3369
3370
3371
3372
3373
3374
3375
3376
3377
3378
3379
3380
3381
3382
3383
3384
3385
3386
3387
3388
3389
3390
3391
3392
3393
3394
3395
3396
3397
3398
3399
3400
3401
  static int try_flush_qgroup(struct btrfs_root *root)
  {
  	struct btrfs_trans_handle *trans;
  	int ret;
  
  	/*
  	 * We don't want to run flush again and again, so if there is a running
  	 * one, we won't try to start a new flush, but exit directly.
  	 */
  	if (test_and_set_bit(BTRFS_ROOT_QGROUP_FLUSHING, &root->state)) {
  		wait_event(root->qgroup_flush_wait,
  			!test_bit(BTRFS_ROOT_QGROUP_FLUSHING, &root->state));
  		return 0;
  	}
  
  	ret = btrfs_start_delalloc_snapshot(root);
  	if (ret < 0)
  		goto out;
  	btrfs_wait_ordered_extents(root, U64_MAX, 0, (u64)-1);
  
  	trans = btrfs_join_transaction(root);
  	if (IS_ERR(trans)) {
  		ret = PTR_ERR(trans);
  		goto out;
  	}
  
  	ret = btrfs_commit_transaction(trans);
  out:
  	clear_bit(BTRFS_ROOT_QGROUP_FLUSHING, &root->state);
  	wake_up(&root->qgroup_flush_wait);
  	return ret;
  }
  
  static int qgroup_reserve_data(struct btrfs_inode *inode,
364ecf365   Qu Wenruo   btrfs: qgroup: In...
3402
3403
  			struct extent_changeset **reserved_ret, u64 start,
  			u64 len)
524725537   Qu Wenruo   btrfs: qgroup: In...
3404
  {
7661a3e03   Nikolay Borisov   btrfs: make btrfs...
3405
  	struct btrfs_root *root = inode->root;
364ecf365   Qu Wenruo   btrfs: qgroup: In...
3406
  	struct extent_changeset *reserved;
263da812e   Qu Wenruo   btrfs: qgroup: al...
3407
  	bool new_reserved = false;
364ecf365   Qu Wenruo   btrfs: qgroup: In...
3408
3409
  	u64 orig_reserved;
  	u64 to_reserve;
524725537   Qu Wenruo   btrfs: qgroup: In...
3410
  	int ret;
afcdd129e   Josef Bacik   Btrfs: add a flag...
3411
  	if (!test_bit(BTRFS_FS_QUOTA_ENABLED, &root->fs_info->flags) ||
4fd786e6c   Misono Tomohiro   btrfs: Remove 'ob...
3412
  	    !is_fstree(root->root_key.objectid) || len == 0)
524725537   Qu Wenruo   btrfs: qgroup: In...
3413
  		return 0;
364ecf365   Qu Wenruo   btrfs: qgroup: In...
3414
3415
3416
3417
  	/* @reserved parameter is mandatory for qgroup */
  	if (WARN_ON(!reserved_ret))
  		return -EINVAL;
  	if (!*reserved_ret) {
263da812e   Qu Wenruo   btrfs: qgroup: al...
3418
  		new_reserved = true;
364ecf365   Qu Wenruo   btrfs: qgroup: In...
3419
3420
3421
3422
3423
3424
3425
  		*reserved_ret = extent_changeset_alloc();
  		if (!*reserved_ret)
  			return -ENOMEM;
  	}
  	reserved = *reserved_ret;
  	/* Record already reserved space */
  	orig_reserved = reserved->bytes_changed;
7661a3e03   Nikolay Borisov   btrfs: make btrfs...
3426
  	ret = set_record_extent_bits(&inode->io_tree, start,
364ecf365   Qu Wenruo   btrfs: qgroup: In...
3427
3428
3429
3430
  			start + len -1, EXTENT_QGROUP_RESERVED, reserved);
  
  	/* Newly reserved space */
  	to_reserve = reserved->bytes_changed - orig_reserved;
7661a3e03   Nikolay Borisov   btrfs: make btrfs...
3431
  	trace_btrfs_qgroup_reserve_data(&inode->vfs_inode, start, len,
364ecf365   Qu Wenruo   btrfs: qgroup: In...
3432
  					to_reserve, QGROUP_RESERVE);
524725537   Qu Wenruo   btrfs: qgroup: In...
3433
  	if (ret < 0)
263da812e   Qu Wenruo   btrfs: qgroup: al...
3434
  		goto out;
dba213242   Qu Wenruo   btrfs: qgroup: Ma...
3435
  	ret = qgroup_reserve(root, to_reserve, true, BTRFS_QGROUP_RSV_DATA);
524725537   Qu Wenruo   btrfs: qgroup: In...
3436
3437
  	if (ret < 0)
  		goto cleanup;
524725537   Qu Wenruo   btrfs: qgroup: In...
3438
3439
3440
  	return ret;
  
  cleanup:
263da812e   Qu Wenruo   btrfs: qgroup: al...
3441
3442
3443
3444
3445
3446
3447
  	qgroup_unreserve_range(inode, reserved, start, len);
  out:
  	if (new_reserved) {
  		extent_changeset_release(reserved);
  		kfree(reserved);
  		*reserved_ret = NULL;
  	}
524725537   Qu Wenruo   btrfs: qgroup: In...
3448
3449
  	return ret;
  }
f695fdcef   Qu Wenruo   btrfs: qgroup: In...
3450

c53e96536   Qu Wenruo   btrfs: qgroup: tr...
3451
3452
3453
3454
3455
3456
3457
3458
3459
3460
3461
3462
3463
3464
3465
3466
3467
3468
3469
3470
3471
3472
3473
3474
3475
3476
3477
  /*
   * Reserve qgroup space for range [start, start + len).
   *
   * This function will either reserve space from related qgroups or do nothing
   * if the range is already reserved.
   *
   * Return 0 for successful reservation
   * Return <0 for error (including -EQUOT)
   *
   * NOTE: This function may sleep for memory allocation, dirty page flushing and
   *	 commit transaction. So caller should not hold any dirty page locked.
   */
  int btrfs_qgroup_reserve_data(struct btrfs_inode *inode,
  			struct extent_changeset **reserved_ret, u64 start,
  			u64 len)
  {
  	int ret;
  
  	ret = qgroup_reserve_data(inode, reserved_ret, start, len);
  	if (ret <= 0 && ret != -EDQUOT)
  		return ret;
  
  	ret = try_flush_qgroup(inode->root);
  	if (ret < 0)
  		return ret;
  	return qgroup_reserve_data(inode, reserved_ret, start, len);
  }
bc42bda22   Qu Wenruo   btrfs: qgroup: Fi...
3478
  /* Free ranges specified by @reserved, normally in error path */
df2cfd131   Nikolay Borisov   btrfs: make qgrou...
3479
  static int qgroup_free_reserved_data(struct btrfs_inode *inode,
bc42bda22   Qu Wenruo   btrfs: qgroup: Fi...
3480
3481
  			struct extent_changeset *reserved, u64 start, u64 len)
  {
df2cfd131   Nikolay Borisov   btrfs: make qgrou...
3482
  	struct btrfs_root *root = inode->root;
bc42bda22   Qu Wenruo   btrfs: qgroup: Fi...
3483
3484
3485
3486
3487
3488
3489
3490
3491
3492
3493
3494
3495
3496
3497
3498
3499
3500
3501
3502
3503
3504
3505
3506
3507
3508
3509
3510
3511
3512
3513
3514
3515
3516
3517
  	struct ulist_node *unode;
  	struct ulist_iterator uiter;
  	struct extent_changeset changeset;
  	int freed = 0;
  	int ret;
  
  	extent_changeset_init(&changeset);
  	len = round_up(start + len, root->fs_info->sectorsize);
  	start = round_down(start, root->fs_info->sectorsize);
  
  	ULIST_ITER_INIT(&uiter);
  	while ((unode = ulist_next(&reserved->range_changed, &uiter))) {
  		u64 range_start = unode->val;
  		/* unode->aux is the inclusive end */
  		u64 range_len = unode->aux - range_start + 1;
  		u64 free_start;
  		u64 free_len;
  
  		extent_changeset_release(&changeset);
  
  		/* Only free range in range [start, start + len) */
  		if (range_start >= start + len ||
  		    range_start + range_len <= start)
  			continue;
  		free_start = max(range_start, start);
  		free_len = min(start + len, range_start + range_len) -
  			   free_start;
  		/*
  		 * TODO: To also modify reserved->ranges_reserved to reflect
  		 * the modification.
  		 *
  		 * However as long as we free qgroup reserved according to
  		 * EXTENT_QGROUP_RESERVED, we won't double free.
  		 * So not need to rush.
  		 */
df2cfd131   Nikolay Borisov   btrfs: make qgrou...
3518
3519
  		ret = clear_record_extent_bits(&inode->io_tree, free_start,
  				free_start + free_len - 1,
bc42bda22   Qu Wenruo   btrfs: qgroup: Fi...
3520
3521
3522
3523
3524
  				EXTENT_QGROUP_RESERVED, &changeset);
  		if (ret < 0)
  			goto out;
  		freed += changeset.bytes_changed;
  	}
4fd786e6c   Misono Tomohiro   btrfs: Remove 'ob...
3525
  	btrfs_qgroup_free_refroot(root->fs_info, root->root_key.objectid, freed,
d4e5c9205   Qu Wenruo   btrfs: qgroup: Sk...
3526
  				  BTRFS_QGROUP_RSV_DATA);
bc42bda22   Qu Wenruo   btrfs: qgroup: Fi...
3527
3528
3529
3530
3531
  	ret = freed;
  out:
  	extent_changeset_release(&changeset);
  	return ret;
  }
8769af96c   Nikolay Borisov   btrfs: make __btr...
3532
  static int __btrfs_qgroup_release_data(struct btrfs_inode *inode,
bc42bda22   Qu Wenruo   btrfs: qgroup: Fi...
3533
3534
  			struct extent_changeset *reserved, u64 start, u64 len,
  			int free)
f695fdcef   Qu Wenruo   btrfs: qgroup: In...
3535
3536
  {
  	struct extent_changeset changeset;
81fb6f77a   Qu Wenruo   btrfs: qgroup: Ad...
3537
  	int trace_op = QGROUP_RELEASE;
f695fdcef   Qu Wenruo   btrfs: qgroup: In...
3538
  	int ret;
8769af96c   Nikolay Borisov   btrfs: make __btr...
3539
  	if (!test_bit(BTRFS_FS_QUOTA_ENABLED, &inode->root->fs_info->flags))
3628b4ca6   Qu Wenruo   btrfs: qgroup: Av...
3540
  		return 0;
bc42bda22   Qu Wenruo   btrfs: qgroup: Fi...
3541
3542
3543
  	/* In release case, we shouldn't have @reserved */
  	WARN_ON(!free && reserved);
  	if (free && reserved)
8769af96c   Nikolay Borisov   btrfs: make __btr...
3544
  		return qgroup_free_reserved_data(inode, reserved, start, len);
364ecf365   Qu Wenruo   btrfs: qgroup: In...
3545
  	extent_changeset_init(&changeset);
8769af96c   Nikolay Borisov   btrfs: make __btr...
3546
3547
  	ret = clear_record_extent_bits(&inode->io_tree, start, start + len -1,
  				       EXTENT_QGROUP_RESERVED, &changeset);
f695fdcef   Qu Wenruo   btrfs: qgroup: In...
3548
3549
  	if (ret < 0)
  		goto out;
d51ea5dd2   Qu Wenruo   btrfs: qgroup: Re...
3550
  	if (free)
81fb6f77a   Qu Wenruo   btrfs: qgroup: Ad...
3551
  		trace_op = QGROUP_FREE;
8769af96c   Nikolay Borisov   btrfs: make __btr...
3552
  	trace_btrfs_qgroup_release_data(&inode->vfs_inode, start, len,
81fb6f77a   Qu Wenruo   btrfs: qgroup: Ad...
3553
  					changeset.bytes_changed, trace_op);
d51ea5dd2   Qu Wenruo   btrfs: qgroup: Re...
3554
  	if (free)
8769af96c   Nikolay Borisov   btrfs: make __btr...
3555
3556
  		btrfs_qgroup_free_refroot(inode->root->fs_info,
  				inode->root->root_key.objectid,
d4e5c9205   Qu Wenruo   btrfs: qgroup: Sk...
3557
  				changeset.bytes_changed, BTRFS_QGROUP_RSV_DATA);
7bc329c18   Qu Wenruo   btrfs: qgroup: Re...
3558
  	ret = changeset.bytes_changed;
f695fdcef   Qu Wenruo   btrfs: qgroup: In...
3559
  out:
364ecf365   Qu Wenruo   btrfs: qgroup: In...
3560
  	extent_changeset_release(&changeset);
f695fdcef   Qu Wenruo   btrfs: qgroup: In...
3561
3562
3563
3564
3565
3566
3567
3568
  	return ret;
  }
  
  /*
   * Free a reserved space range from io_tree and related qgroups
   *
   * Should be called when a range of pages get invalidated before reaching disk.
   * Or for error cleanup case.
bc42bda22   Qu Wenruo   btrfs: qgroup: Fi...
3569
3570
   * if @reserved is given, only reserved range in [@start, @start + @len) will
   * be freed.
f695fdcef   Qu Wenruo   btrfs: qgroup: In...
3571
3572
3573
3574
3575
   *
   * For data written to disk, use btrfs_qgroup_release_data().
   *
   * NOTE: This function may sleep for memory allocation.
   */
8b8a979f1   Nikolay Borisov   btrfs: make btrfs...
3576
  int btrfs_qgroup_free_data(struct btrfs_inode *inode,
bc42bda22   Qu Wenruo   btrfs: qgroup: Fi...
3577
  			struct extent_changeset *reserved, u64 start, u64 len)
f695fdcef   Qu Wenruo   btrfs: qgroup: In...
3578
  {
8b8a979f1   Nikolay Borisov   btrfs: make btrfs...
3579
  	return __btrfs_qgroup_release_data(inode, reserved, start, len, 1);
f695fdcef   Qu Wenruo   btrfs: qgroup: In...
3580
3581
3582
3583
3584
3585
3586
3587
3588
3589
3590
3591
3592
3593
3594
3595
3596
  }
  
  /*
   * Release a reserved space range from io_tree only.
   *
   * Should be called when a range of pages get written to disk and corresponding
   * FILE_EXTENT is inserted into corresponding root.
   *
   * Since new qgroup accounting framework will only update qgroup numbers at
   * commit_transaction() time, its reserved space shouldn't be freed from
   * related qgroups.
   *
   * But we should release the range from io_tree, to allow further write to be
   * COWed.
   *
   * NOTE: This function may sleep for memory allocation.
   */
72b7d15bf   Nikolay Borisov   btrfs: make btrfs...
3597
  int btrfs_qgroup_release_data(struct btrfs_inode *inode, u64 start, u64 len)
f695fdcef   Qu Wenruo   btrfs: qgroup: In...
3598
  {
72b7d15bf   Nikolay Borisov   btrfs: make btrfs...
3599
  	return __btrfs_qgroup_release_data(inode, NULL, start, len, 0);
f695fdcef   Qu Wenruo   btrfs: qgroup: In...
3600
  }
55eeaf057   Qu Wenruo   btrfs: qgroup: In...
3601

8287475a2   Qu Wenruo   btrfs: qgroup: Us...
3602
3603
3604
3605
3606
3607
3608
3609
3610
3611
3612
3613
3614
3615
3616
3617
3618
3619
3620
3621
3622
3623
3624
3625
3626
3627
3628
3629
3630
3631
3632
3633
3634
3635
3636
3637
3638
3639
3640
  static void add_root_meta_rsv(struct btrfs_root *root, int num_bytes,
  			      enum btrfs_qgroup_rsv_type type)
  {
  	if (type != BTRFS_QGROUP_RSV_META_PREALLOC &&
  	    type != BTRFS_QGROUP_RSV_META_PERTRANS)
  		return;
  	if (num_bytes == 0)
  		return;
  
  	spin_lock(&root->qgroup_meta_rsv_lock);
  	if (type == BTRFS_QGROUP_RSV_META_PREALLOC)
  		root->qgroup_meta_rsv_prealloc += num_bytes;
  	else
  		root->qgroup_meta_rsv_pertrans += num_bytes;
  	spin_unlock(&root->qgroup_meta_rsv_lock);
  }
  
  static int sub_root_meta_rsv(struct btrfs_root *root, int num_bytes,
  			     enum btrfs_qgroup_rsv_type type)
  {
  	if (type != BTRFS_QGROUP_RSV_META_PREALLOC &&
  	    type != BTRFS_QGROUP_RSV_META_PERTRANS)
  		return 0;
  	if (num_bytes == 0)
  		return 0;
  
  	spin_lock(&root->qgroup_meta_rsv_lock);
  	if (type == BTRFS_QGROUP_RSV_META_PREALLOC) {
  		num_bytes = min_t(u64, root->qgroup_meta_rsv_prealloc,
  				  num_bytes);
  		root->qgroup_meta_rsv_prealloc -= num_bytes;
  	} else {
  		num_bytes = min_t(u64, root->qgroup_meta_rsv_pertrans,
  				  num_bytes);
  		root->qgroup_meta_rsv_pertrans -= num_bytes;
  	}
  	spin_unlock(&root->qgroup_meta_rsv_lock);
  	return num_bytes;
  }
c53e96536   Qu Wenruo   btrfs: qgroup: tr...
3641
  static int qgroup_reserve_meta(struct btrfs_root *root, int num_bytes,
733e03a0b   Qu Wenruo   btrfs: qgroup: Sp...
3642
  				enum btrfs_qgroup_rsv_type type, bool enforce)
55eeaf057   Qu Wenruo   btrfs: qgroup: In...
3643
  {
0b246afa6   Jeff Mahoney   btrfs: root->fs_i...
3644
  	struct btrfs_fs_info *fs_info = root->fs_info;
55eeaf057   Qu Wenruo   btrfs: qgroup: In...
3645
  	int ret;
0b246afa6   Jeff Mahoney   btrfs: root->fs_i...
3646
  	if (!test_bit(BTRFS_FS_QUOTA_ENABLED, &fs_info->flags) ||
4fd786e6c   Misono Tomohiro   btrfs: Remove 'ob...
3647
  	    !is_fstree(root->root_key.objectid) || num_bytes == 0)
55eeaf057   Qu Wenruo   btrfs: qgroup: In...
3648
  		return 0;
0b246afa6   Jeff Mahoney   btrfs: root->fs_i...
3649
  	BUG_ON(num_bytes != round_down(num_bytes, fs_info->nodesize));
fd2b007ea   Qu Wenruo   btrfs: tracepoint...
3650
  	trace_qgroup_meta_reserve(root, (s64)num_bytes, type);
733e03a0b   Qu Wenruo   btrfs: qgroup: Sp...
3651
  	ret = qgroup_reserve(root, num_bytes, enforce, type);
55eeaf057   Qu Wenruo   btrfs: qgroup: In...
3652
3653
  	if (ret < 0)
  		return ret;
8287475a2   Qu Wenruo   btrfs: qgroup: Us...
3654
3655
3656
3657
3658
3659
3660
3661
3662
  	/*
  	 * Record what we have reserved into root.
  	 *
  	 * To avoid quota disabled->enabled underflow.
  	 * In that case, we may try to free space we haven't reserved
  	 * (since quota was disabled), so record what we reserved into root.
  	 * And ensure later release won't underflow this number.
  	 */
  	add_root_meta_rsv(root, num_bytes, type);
55eeaf057   Qu Wenruo   btrfs: qgroup: In...
3663
3664
  	return ret;
  }
c53e96536   Qu Wenruo   btrfs: qgroup: tr...
3665
3666
3667
3668
3669
3670
3671
3672
3673
3674
3675
3676
3677
3678
  int __btrfs_qgroup_reserve_meta(struct btrfs_root *root, int num_bytes,
  				enum btrfs_qgroup_rsv_type type, bool enforce)
  {
  	int ret;
  
  	ret = qgroup_reserve_meta(root, num_bytes, type, enforce);
  	if (ret <= 0 && ret != -EDQUOT)
  		return ret;
  
  	ret = try_flush_qgroup(root);
  	if (ret < 0)
  		return ret;
  	return qgroup_reserve_meta(root, num_bytes, type, enforce);
  }
733e03a0b   Qu Wenruo   btrfs: qgroup: Sp...
3679
  void btrfs_qgroup_free_meta_all_pertrans(struct btrfs_root *root)
55eeaf057   Qu Wenruo   btrfs: qgroup: In...
3680
  {
0b246afa6   Jeff Mahoney   btrfs: root->fs_i...
3681
  	struct btrfs_fs_info *fs_info = root->fs_info;
55eeaf057   Qu Wenruo   btrfs: qgroup: In...
3682

0b246afa6   Jeff Mahoney   btrfs: root->fs_i...
3683
  	if (!test_bit(BTRFS_FS_QUOTA_ENABLED, &fs_info->flags) ||
4fd786e6c   Misono Tomohiro   btrfs: Remove 'ob...
3684
  	    !is_fstree(root->root_key.objectid))
55eeaf057   Qu Wenruo   btrfs: qgroup: In...
3685
  		return;
e1211d0e8   Qu Wenruo   btrfs: qgroup: Do...
3686
  	/* TODO: Update trace point to handle such free */
4ee0d8832   Qu Wenruo   btrfs: qgroup: Up...
3687
  	trace_qgroup_meta_free_all_pertrans(root);
e1211d0e8   Qu Wenruo   btrfs: qgroup: Do...
3688
  	/* Special value -1 means to free all reserved space */
4fd786e6c   Misono Tomohiro   btrfs: Remove 'ob...
3689
  	btrfs_qgroup_free_refroot(fs_info, root->root_key.objectid, (u64)-1,
733e03a0b   Qu Wenruo   btrfs: qgroup: Sp...
3690
  				  BTRFS_QGROUP_RSV_META_PERTRANS);
55eeaf057   Qu Wenruo   btrfs: qgroup: In...
3691
  }
733e03a0b   Qu Wenruo   btrfs: qgroup: Sp...
3692
3693
  void __btrfs_qgroup_free_meta(struct btrfs_root *root, int num_bytes,
  			      enum btrfs_qgroup_rsv_type type)
55eeaf057   Qu Wenruo   btrfs: qgroup: In...
3694
  {
0b246afa6   Jeff Mahoney   btrfs: root->fs_i...
3695
3696
3697
  	struct btrfs_fs_info *fs_info = root->fs_info;
  
  	if (!test_bit(BTRFS_FS_QUOTA_ENABLED, &fs_info->flags) ||
4fd786e6c   Misono Tomohiro   btrfs: Remove 'ob...
3698
  	    !is_fstree(root->root_key.objectid))
55eeaf057   Qu Wenruo   btrfs: qgroup: In...
3699
  		return;
8287475a2   Qu Wenruo   btrfs: qgroup: Us...
3700
3701
3702
3703
3704
3705
  	/*
  	 * reservation for META_PREALLOC can happen before quota is enabled,
  	 * which can lead to underflow.
  	 * Here ensure we will only free what we really have reserved.
  	 */
  	num_bytes = sub_root_meta_rsv(root, num_bytes, type);
0b246afa6   Jeff Mahoney   btrfs: root->fs_i...
3706
  	BUG_ON(num_bytes != round_down(num_bytes, fs_info->nodesize));
fd2b007ea   Qu Wenruo   btrfs: tracepoint...
3707
  	trace_qgroup_meta_reserve(root, -(s64)num_bytes, type);
4fd786e6c   Misono Tomohiro   btrfs: Remove 'ob...
3708
3709
  	btrfs_qgroup_free_refroot(fs_info, root->root_key.objectid,
  				  num_bytes, type);
55eeaf057   Qu Wenruo   btrfs: qgroup: In...
3710
  }
56fa9d076   Qu Wenruo   btrfs: qgroup: Ch...
3711

64cfaef63   Qu Wenruo   btrfs: qgroup: In...
3712
3713
3714
  static void qgroup_convert_meta(struct btrfs_fs_info *fs_info, u64 ref_root,
  				int num_bytes)
  {
64cfaef63   Qu Wenruo   btrfs: qgroup: In...
3715
3716
3717
3718
3719
3720
3721
  	struct btrfs_qgroup *qgroup;
  	struct ulist_node *unode;
  	struct ulist_iterator uiter;
  	int ret = 0;
  
  	if (num_bytes == 0)
  		return;
e3b0edd29   Marcos Paulo de Souza   btrfs: qgroup: re...
3722
  	if (!fs_info->quota_root)
64cfaef63   Qu Wenruo   btrfs: qgroup: In...
3723
3724
3725
3726
3727
3728
3729
3730
  		return;
  
  	spin_lock(&fs_info->qgroup_lock);
  	qgroup = find_qgroup_rb(fs_info, ref_root);
  	if (!qgroup)
  		goto out;
  	ulist_reinit(fs_info->qgroup_ulist);
  	ret = ulist_add(fs_info->qgroup_ulist, qgroup->qgroupid,
a1840b502   David Sterba   btrfs: use helper...
3731
  		       qgroup_to_aux(qgroup), GFP_ATOMIC);
64cfaef63   Qu Wenruo   btrfs: qgroup: In...
3732
3733
3734
3735
3736
3737
3738
3739
3740
3741
3742
3743
3744
3745
3746
3747
  	if (ret < 0)
  		goto out;
  	ULIST_ITER_INIT(&uiter);
  	while ((unode = ulist_next(fs_info->qgroup_ulist, &uiter))) {
  		struct btrfs_qgroup *qg;
  		struct btrfs_qgroup_list *glist;
  
  		qg = unode_aux_to_qgroup(unode);
  
  		qgroup_rsv_release(fs_info, qg, num_bytes,
  				BTRFS_QGROUP_RSV_META_PREALLOC);
  		qgroup_rsv_add(fs_info, qg, num_bytes,
  				BTRFS_QGROUP_RSV_META_PERTRANS);
  		list_for_each_entry(glist, &qg->groups, next_group) {
  			ret = ulist_add(fs_info->qgroup_ulist,
  					glist->group->qgroupid,
a1840b502   David Sterba   btrfs: use helper...
3748
  					qgroup_to_aux(glist->group), GFP_ATOMIC);
64cfaef63   Qu Wenruo   btrfs: qgroup: In...
3749
3750
3751
3752
3753
3754
3755
3756
3757
3758
3759
3760
3761
  			if (ret < 0)
  				goto out;
  		}
  	}
  out:
  	spin_unlock(&fs_info->qgroup_lock);
  }
  
  void btrfs_qgroup_convert_reserved_meta(struct btrfs_root *root, int num_bytes)
  {
  	struct btrfs_fs_info *fs_info = root->fs_info;
  
  	if (!test_bit(BTRFS_FS_QUOTA_ENABLED, &fs_info->flags) ||
4fd786e6c   Misono Tomohiro   btrfs: Remove 'ob...
3762
  	    !is_fstree(root->root_key.objectid))
64cfaef63   Qu Wenruo   btrfs: qgroup: In...
3763
  		return;
8287475a2   Qu Wenruo   btrfs: qgroup: Us...
3764
3765
3766
  	/* Same as btrfs_qgroup_free_meta_prealloc() */
  	num_bytes = sub_root_meta_rsv(root, num_bytes,
  				      BTRFS_QGROUP_RSV_META_PREALLOC);
4ee0d8832   Qu Wenruo   btrfs: qgroup: Up...
3767
  	trace_qgroup_meta_convert(root, num_bytes);
4fd786e6c   Misono Tomohiro   btrfs: Remove 'ob...
3768
  	qgroup_convert_meta(fs_info, root->root_key.objectid, num_bytes);
64cfaef63   Qu Wenruo   btrfs: qgroup: In...
3769
  }
56fa9d076   Qu Wenruo   btrfs: qgroup: Ch...
3770
  /*
013276101   Nicholas D Steeves   btrfs: fix string...
3771
   * Check qgroup reserved space leaking, normally at destroy inode
56fa9d076   Qu Wenruo   btrfs: qgroup: Ch...
3772
3773
   * time
   */
cfdd45921   Nikolay Borisov   btrfs: make btrfs...
3774
  void btrfs_qgroup_check_reserved_leak(struct btrfs_inode *inode)
56fa9d076   Qu Wenruo   btrfs: qgroup: Ch...
3775
3776
3777
3778
3779
  {
  	struct extent_changeset changeset;
  	struct ulist_node *unode;
  	struct ulist_iterator iter;
  	int ret;
364ecf365   Qu Wenruo   btrfs: qgroup: In...
3780
  	extent_changeset_init(&changeset);
cfdd45921   Nikolay Borisov   btrfs: make btrfs...
3781
  	ret = clear_record_extent_bits(&inode->io_tree, 0, (u64)-1,
f734c44a1   David Sterba   btrfs: sink gfp p...
3782
  			EXTENT_QGROUP_RESERVED, &changeset);
56fa9d076   Qu Wenruo   btrfs: qgroup: Ch...
3783
3784
3785
3786
  
  	WARN_ON(ret < 0);
  	if (WARN_ON(changeset.bytes_changed)) {
  		ULIST_ITER_INIT(&iter);
53d323599   David Sterba   btrfs: embed exte...
3787
  		while ((unode = ulist_next(&changeset.range_changed, &iter))) {
cfdd45921   Nikolay Borisov   btrfs: make btrfs...
3788
3789
3790
  			btrfs_warn(inode->root->fs_info,
  		"leaking qgroup reserved space, ino: %llu, start: %llu, end: %llu",
  				btrfs_ino(inode), unode->val, unode->aux);
56fa9d076   Qu Wenruo   btrfs: qgroup: Ch...
3791
  		}
cfdd45921   Nikolay Borisov   btrfs: make btrfs...
3792
3793
  		btrfs_qgroup_free_refroot(inode->root->fs_info,
  				inode->root->root_key.objectid,
d4e5c9205   Qu Wenruo   btrfs: qgroup: Sk...
3794
  				changeset.bytes_changed, BTRFS_QGROUP_RSV_DATA);
0b08e1f4f   David Sterba   btrfs: qgroups: o...
3795

56fa9d076   Qu Wenruo   btrfs: qgroup: Ch...
3796
  	}
364ecf365   Qu Wenruo   btrfs: qgroup: In...
3797
  	extent_changeset_release(&changeset);
56fa9d076   Qu Wenruo   btrfs: qgroup: Ch...
3798
  }
370a11b81   Qu Wenruo   btrfs: qgroup: In...
3799
3800
3801
3802
3803
3804
3805
3806
3807
3808
3809
3810
3811
3812
3813
3814
3815
3816
3817
3818
3819
3820
3821
3822
3823
3824
3825
3826
3827
3828
3829
3830
3831
3832
3833
3834
3835
3836
3837
3838
3839
3840
3841
3842
3843
3844
3845
3846
3847
3848
3849
3850
3851
3852
3853
  
  void btrfs_qgroup_init_swapped_blocks(
  	struct btrfs_qgroup_swapped_blocks *swapped_blocks)
  {
  	int i;
  
  	spin_lock_init(&swapped_blocks->lock);
  	for (i = 0; i < BTRFS_MAX_LEVEL; i++)
  		swapped_blocks->blocks[i] = RB_ROOT;
  	swapped_blocks->swapped = false;
  }
  
  /*
   * Delete all swapped blocks record of @root.
   * Every record here means we skipped a full subtree scan for qgroup.
   *
   * Gets called when committing one transaction.
   */
  void btrfs_qgroup_clean_swapped_blocks(struct btrfs_root *root)
  {
  	struct btrfs_qgroup_swapped_blocks *swapped_blocks;
  	int i;
  
  	swapped_blocks = &root->swapped_blocks;
  
  	spin_lock(&swapped_blocks->lock);
  	if (!swapped_blocks->swapped)
  		goto out;
  	for (i = 0; i < BTRFS_MAX_LEVEL; i++) {
  		struct rb_root *cur_root = &swapped_blocks->blocks[i];
  		struct btrfs_qgroup_swapped_block *entry;
  		struct btrfs_qgroup_swapped_block *next;
  
  		rbtree_postorder_for_each_entry_safe(entry, next, cur_root,
  						     node)
  			kfree(entry);
  		swapped_blocks->blocks[i] = RB_ROOT;
  	}
  	swapped_blocks->swapped = false;
  out:
  	spin_unlock(&swapped_blocks->lock);
  }
  
  /*
   * Add subtree roots record into @subvol_root.
   *
   * @subvol_root:	tree root of the subvolume tree get swapped
   * @bg:			block group under balance
   * @subvol_parent/slot:	pointer to the subtree root in subvolume tree
   * @reloc_parent/slot:	pointer to the subtree root in reloc tree
   *			BOTH POINTERS ARE BEFORE TREE SWAP
   * @last_snapshot:	last snapshot generation of the subvolume tree
   */
  int btrfs_qgroup_add_swapped_blocks(struct btrfs_trans_handle *trans,
  		struct btrfs_root *subvol_root,
32da5386d   David Sterba   btrfs: rename btr...
3854
  		struct btrfs_block_group *bg,
370a11b81   Qu Wenruo   btrfs: qgroup: In...
3855
3856
3857
3858
3859
3860
3861
3862
3863
3864
3865
3866
3867
3868
3869
3870
3871
3872
3873
3874
3875
3876
3877
3878
3879
3880
3881
3882
3883
3884
3885
3886
3887
3888
3889
3890
3891
3892
3893
3894
3895
3896
3897
  		struct extent_buffer *subvol_parent, int subvol_slot,
  		struct extent_buffer *reloc_parent, int reloc_slot,
  		u64 last_snapshot)
  {
  	struct btrfs_fs_info *fs_info = subvol_root->fs_info;
  	struct btrfs_qgroup_swapped_blocks *blocks = &subvol_root->swapped_blocks;
  	struct btrfs_qgroup_swapped_block *block;
  	struct rb_node **cur;
  	struct rb_node *parent = NULL;
  	int level = btrfs_header_level(subvol_parent) - 1;
  	int ret = 0;
  
  	if (!test_bit(BTRFS_FS_QUOTA_ENABLED, &fs_info->flags))
  		return 0;
  
  	if (btrfs_node_ptr_generation(subvol_parent, subvol_slot) >
  	    btrfs_node_ptr_generation(reloc_parent, reloc_slot)) {
  		btrfs_err_rl(fs_info,
  		"%s: bad parameter order, subvol_gen=%llu reloc_gen=%llu",
  			__func__,
  			btrfs_node_ptr_generation(subvol_parent, subvol_slot),
  			btrfs_node_ptr_generation(reloc_parent, reloc_slot));
  		return -EUCLEAN;
  	}
  
  	block = kmalloc(sizeof(*block), GFP_NOFS);
  	if (!block) {
  		ret = -ENOMEM;
  		goto out;
  	}
  
  	/*
  	 * @reloc_parent/slot is still before swap, while @block is going to
  	 * record the bytenr after swap, so we do the swap here.
  	 */
  	block->subvol_bytenr = btrfs_node_blockptr(reloc_parent, reloc_slot);
  	block->subvol_generation = btrfs_node_ptr_generation(reloc_parent,
  							     reloc_slot);
  	block->reloc_bytenr = btrfs_node_blockptr(subvol_parent, subvol_slot);
  	block->reloc_generation = btrfs_node_ptr_generation(subvol_parent,
  							    subvol_slot);
  	block->last_snapshot = last_snapshot;
  	block->level = level;
57949d033   Qu Wenruo   btrfs: qgroup: Ch...
3898
3899
3900
3901
3902
3903
3904
  
  	/*
  	 * If we have bg == NULL, we're called from btrfs_recover_relocation(),
  	 * no one else can modify tree blocks thus we qgroup will not change
  	 * no matter the value of trace_leaf.
  	 */
  	if (bg && bg->flags & BTRFS_BLOCK_GROUP_DATA)
370a11b81   Qu Wenruo   btrfs: qgroup: In...
3905
3906
3907
3908
3909
3910
3911
3912
3913
3914
3915
3916
3917
3918
3919
3920
3921
3922
3923
3924
3925
3926
3927
3928
3929
3930
3931
3932
3933
3934
3935
3936
3937
3938
3939
3940
3941
3942
3943
3944
3945
3946
3947
3948
3949
3950
3951
3952
3953
3954
  		block->trace_leaf = true;
  	else
  		block->trace_leaf = false;
  	btrfs_node_key_to_cpu(reloc_parent, &block->first_key, reloc_slot);
  
  	/* Insert @block into @blocks */
  	spin_lock(&blocks->lock);
  	cur = &blocks->blocks[level].rb_node;
  	while (*cur) {
  		struct btrfs_qgroup_swapped_block *entry;
  
  		parent = *cur;
  		entry = rb_entry(parent, struct btrfs_qgroup_swapped_block,
  				 node);
  
  		if (entry->subvol_bytenr < block->subvol_bytenr) {
  			cur = &(*cur)->rb_left;
  		} else if (entry->subvol_bytenr > block->subvol_bytenr) {
  			cur = &(*cur)->rb_right;
  		} else {
  			if (entry->subvol_generation !=
  					block->subvol_generation ||
  			    entry->reloc_bytenr != block->reloc_bytenr ||
  			    entry->reloc_generation !=
  					block->reloc_generation) {
  				/*
  				 * Duplicated but mismatch entry found.
  				 * Shouldn't happen.
  				 *
  				 * Marking qgroup inconsistent should be enough
  				 * for end users.
  				 */
  				WARN_ON(IS_ENABLED(CONFIG_BTRFS_DEBUG));
  				ret = -EEXIST;
  			}
  			kfree(block);
  			goto out_unlock;
  		}
  	}
  	rb_link_node(&block->node, parent, cur);
  	rb_insert_color(&block->node, &blocks->blocks[level]);
  	blocks->swapped = true;
  out_unlock:
  	spin_unlock(&blocks->lock);
  out:
  	if (ret < 0)
  		fs_info->qgroup_flags |=
  			BTRFS_QGROUP_STATUS_FLAG_INCONSISTENT;
  	return ret;
  }
f616f5cd9   Qu Wenruo   btrfs: qgroup: Us...
3955
3956
3957
3958
3959
3960
3961
3962
3963
3964
3965
3966
3967
3968
3969
3970
3971
3972
3973
3974
3975
3976
3977
3978
3979
3980
3981
3982
3983
3984
3985
3986
3987
3988
3989
3990
3991
3992
3993
3994
3995
3996
3997
3998
3999
4000
4001
4002
4003
4004
4005
4006
4007
4008
4009
4010
4011
4012
4013
4014
4015
4016
4017
4018
4019
4020
4021
4022
4023
4024
4025
4026
4027
4028
4029
4030
4031
4032
4033
4034
4035
4036
4037
4038
4039
4040
4041
4042
  
  /*
   * Check if the tree block is a subtree root, and if so do the needed
   * delayed subtree trace for qgroup.
   *
   * This is called during btrfs_cow_block().
   */
  int btrfs_qgroup_trace_subtree_after_cow(struct btrfs_trans_handle *trans,
  					 struct btrfs_root *root,
  					 struct extent_buffer *subvol_eb)
  {
  	struct btrfs_fs_info *fs_info = root->fs_info;
  	struct btrfs_qgroup_swapped_blocks *blocks = &root->swapped_blocks;
  	struct btrfs_qgroup_swapped_block *block;
  	struct extent_buffer *reloc_eb = NULL;
  	struct rb_node *node;
  	bool found = false;
  	bool swapped = false;
  	int level = btrfs_header_level(subvol_eb);
  	int ret = 0;
  	int i;
  
  	if (!test_bit(BTRFS_FS_QUOTA_ENABLED, &fs_info->flags))
  		return 0;
  	if (!is_fstree(root->root_key.objectid) || !root->reloc_root)
  		return 0;
  
  	spin_lock(&blocks->lock);
  	if (!blocks->swapped) {
  		spin_unlock(&blocks->lock);
  		return 0;
  	}
  	node = blocks->blocks[level].rb_node;
  
  	while (node) {
  		block = rb_entry(node, struct btrfs_qgroup_swapped_block, node);
  		if (block->subvol_bytenr < subvol_eb->start) {
  			node = node->rb_left;
  		} else if (block->subvol_bytenr > subvol_eb->start) {
  			node = node->rb_right;
  		} else {
  			found = true;
  			break;
  		}
  	}
  	if (!found) {
  		spin_unlock(&blocks->lock);
  		goto out;
  	}
  	/* Found one, remove it from @blocks first and update blocks->swapped */
  	rb_erase(&block->node, &blocks->blocks[level]);
  	for (i = 0; i < BTRFS_MAX_LEVEL; i++) {
  		if (RB_EMPTY_ROOT(&blocks->blocks[i])) {
  			swapped = true;
  			break;
  		}
  	}
  	blocks->swapped = swapped;
  	spin_unlock(&blocks->lock);
  
  	/* Read out reloc subtree root */
  	reloc_eb = read_tree_block(fs_info, block->reloc_bytenr,
  				   block->reloc_generation, block->level,
  				   &block->first_key);
  	if (IS_ERR(reloc_eb)) {
  		ret = PTR_ERR(reloc_eb);
  		reloc_eb = NULL;
  		goto free_out;
  	}
  	if (!extent_buffer_uptodate(reloc_eb)) {
  		ret = -EIO;
  		goto free_out;
  	}
  
  	ret = qgroup_trace_subtree_swap(trans, reloc_eb, subvol_eb,
  			block->last_snapshot, block->trace_leaf);
  free_out:
  	kfree(block);
  	free_extent_buffer(reloc_eb);
  out:
  	if (ret < 0) {
  		btrfs_err_rl(fs_info,
  			     "failed to account subtree at bytenr %llu: %d",
  			     subvol_eb->start, ret);
  		fs_info->qgroup_flags |= BTRFS_QGROUP_STATUS_FLAG_INCONSISTENT;
  	}
  	return ret;
  }
81f7eb00f   Jeff Mahoney   btrfs: destroy qg...
4043
4044
4045
4046
4047
4048
4049
4050
4051
4052
4053
4054
4055
  
  void btrfs_qgroup_destroy_extent_records(struct btrfs_transaction *trans)
  {
  	struct btrfs_qgroup_extent_record *entry;
  	struct btrfs_qgroup_extent_record *next;
  	struct rb_root *root;
  
  	root = &trans->delayed_refs.dirty_extent_root;
  	rbtree_postorder_for_each_entry_safe(entry, next, root, node) {
  		ulist_free(entry->old_roots);
  		kfree(entry);
  	}
  }