btrfs-progs: ci: cache built dependencies
[platform/upstream/btrfs-progs.git] / qgroup.c
1 /*
2  * Copyright (C) 2012 STRATO.  All rights reserved.
3  *
4  * This program is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU General Public
6  * License v2 as published by the Free Software Foundation.
7  *
8  * This program is distributed in the hope that it will be useful,
9  * but WITHOUT ANY WARRANTY; without even the implied warranty of
10  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
11  * General Public License for more details.
12  *
13  * You should have received a copy of the GNU General Public
14  * License along with this program; if not, write to the
15  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
16  * Boston, MA 021110-1307, USA.
17  */
18
19 #include "qgroup.h"
20 #include <sys/ioctl.h>
21 #include "ctree.h"
22 #include "ioctl.h"
23 #include "utils.h"
24 #include <errno.h>
25
26 #define BTRFS_QGROUP_NFILTERS_INCREASE (2 * BTRFS_QGROUP_FILTER_MAX)
27 #define BTRFS_QGROUP_NCOMPS_INCREASE (2 * BTRFS_QGROUP_COMP_MAX)
28
29 struct qgroup_lookup {
30         struct rb_root root;
31 };
32
33 struct btrfs_qgroup {
34         struct rb_node rb_node;
35         struct rb_node sort_node;
36         /*
37          *all_parent_node is used to
38          *filter a qgroup's all parent
39          */
40         struct rb_node all_parent_node;
41         u64 qgroupid;
42
43         /*
44          * info_item
45          */
46         u64 generation;
47         u64 rfer;       /*referenced*/
48         u64 rfer_cmpr;  /*referenced compressed*/
49         u64 excl;       /*exclusive*/
50         u64 excl_cmpr;  /*exclusive compressed*/
51
52         /*
53          *limit_item
54          */
55         u64 flags;      /*which limits are set*/
56         u64 max_rfer;
57         u64 max_excl;
58         u64 rsv_rfer;
59         u64 rsv_excl;
60
61         /*qgroups this group is member of*/
62         struct list_head qgroups;
63         /*qgroups that are members of this group*/
64         struct list_head members;
65 };
66
67 /*
68  * glue structure to represent the relations
69  * between qgroups
70  */
71 struct btrfs_qgroup_list {
72         struct list_head next_qgroup;
73         struct list_head next_member;
74         struct btrfs_qgroup *qgroup;
75         struct btrfs_qgroup *member;
76 };
77
78 /*
79  * qgroupid,rfer,excl default to set
80  */
81 static struct {
82         char *name;
83         char *column_name;
84         int need_print;
85         unsigned unit_mode;
86         int max_len;
87 } btrfs_qgroup_columns[] = {
88         {
89                 .name           = "qgroupid",
90                 .column_name    = "Qgroupid",
91                 .need_print     = 1,
92                 .unit_mode      = 0,
93                 .max_len        = 8,
94         },
95         {
96                 .name           = "rfer",
97                 .column_name    = "Rfer",
98                 .need_print     = 1,
99                 .unit_mode      = UNITS_DEFAULT,
100                 .max_len        = 12,
101         },
102         {
103                 .name           = "excl",
104                 .column_name    = "Excl",
105                 .need_print     = 1,
106                 .unit_mode      = UNITS_DEFAULT,
107                 .max_len        = 12,
108         },
109         {       .name           = "max_rfer",
110                 .column_name    = "Max_rfer",
111                 .need_print     = 0,
112                 .unit_mode      = UNITS_DEFAULT,
113                 .max_len        = 12,
114         },
115         {
116                 .name           = "max_excl",
117                 .column_name    = "Max_excl",
118                 .need_print     = 0,
119                 .unit_mode      = UNITS_DEFAULT,
120                 .max_len        = 12,
121         },
122         {
123                 .name           = "parent",
124                 .column_name    = "Parent",
125                 .need_print     = 0,
126                 .unit_mode      = 0,
127                 .max_len        = 7,
128         },
129         {
130                 .name           = "child",
131                 .column_name    = "Child",
132                 .need_print     = 0,
133                 .unit_mode      = 0,
134                 .max_len        = 5,
135         },
136         {
137                 .name           = NULL,
138                 .column_name    = NULL,
139                 .need_print     = 0,
140                 .unit_mode      = 0,
141         },
142 };
143
144 static btrfs_qgroup_filter_func all_filter_funcs[];
145 static btrfs_qgroup_comp_func all_comp_funcs[];
146
147 void btrfs_qgroup_setup_print_column(enum btrfs_qgroup_column_enum column)
148 {
149         int i;
150
151         ASSERT(0 <= column && column <= BTRFS_QGROUP_ALL);
152
153         if (column < BTRFS_QGROUP_ALL) {
154                 btrfs_qgroup_columns[column].need_print = 1;
155                 return;
156         }
157         for (i = 0; i < BTRFS_QGROUP_ALL; i++)
158                 btrfs_qgroup_columns[i].need_print = 1;
159 }
160
161 void btrfs_qgroup_setup_units(unsigned unit_mode)
162 {
163         btrfs_qgroup_columns[BTRFS_QGROUP_RFER].unit_mode = unit_mode;
164         btrfs_qgroup_columns[BTRFS_QGROUP_EXCL].unit_mode = unit_mode;
165         btrfs_qgroup_columns[BTRFS_QGROUP_MAX_RFER].unit_mode = unit_mode;
166         btrfs_qgroup_columns[BTRFS_QGROUP_MAX_EXCL].unit_mode = unit_mode;
167 }
168
169 static int print_parent_column(struct btrfs_qgroup *qgroup)
170 {
171         struct btrfs_qgroup_list *list = NULL;
172         int len = 0;
173
174         list_for_each_entry(list, &qgroup->qgroups, next_qgroup) {
175                 len += printf("%llu/%llu",
176                               btrfs_qgroup_level(list->qgroup->qgroupid),
177                               btrfs_qgroup_subvid(list->qgroup->qgroupid));
178                 if (!list_is_last(&list->next_qgroup, &qgroup->qgroups))
179                         len += printf(",");
180         }
181         if (list_empty(&qgroup->qgroups))
182                 len += printf("---");
183
184         return len;
185 }
186
187 static int print_child_column(struct btrfs_qgroup *qgroup)
188 {
189         struct btrfs_qgroup_list *list = NULL;
190         int len = 0;
191
192         list_for_each_entry(list, &qgroup->members, next_member) {
193                 len += printf("%llu/%llu",
194                               btrfs_qgroup_level(list->member->qgroupid),
195                               btrfs_qgroup_subvid(list->member->qgroupid));
196                 if (!list_is_last(&list->next_member, &qgroup->members))
197                         len += printf(",");
198         }
199         if (list_empty(&qgroup->members))
200                 len += printf("---");
201
202         return len;
203 }
204
205 static void print_qgroup_column_add_blank(enum btrfs_qgroup_column_enum column,
206                                           int len)
207 {
208         len = btrfs_qgroup_columns[column].max_len - len;
209         while (len--)
210                 printf(" ");
211 }
212
213 static void print_qgroup_column(struct btrfs_qgroup *qgroup,
214                                 enum btrfs_qgroup_column_enum column)
215 {
216         int len;
217         int unit_mode = btrfs_qgroup_columns[column].unit_mode;
218         int max_len = btrfs_qgroup_columns[column].max_len;
219
220         ASSERT(0 <= column && column < BTRFS_QGROUP_ALL);
221
222         switch (column) {
223
224         case BTRFS_QGROUP_QGROUPID:
225                 len = printf("%llu/%llu",
226                              btrfs_qgroup_level(qgroup->qgroupid),
227                              btrfs_qgroup_subvid(qgroup->qgroupid));
228                 print_qgroup_column_add_blank(BTRFS_QGROUP_QGROUPID, len);
229                 break;
230         case BTRFS_QGROUP_RFER:
231                 len = printf("%*s", max_len, pretty_size_mode(qgroup->rfer, unit_mode));
232                 break;
233         case BTRFS_QGROUP_EXCL:
234                 len = printf("%*s", max_len, pretty_size_mode(qgroup->excl, unit_mode));
235                 break;
236         case BTRFS_QGROUP_PARENT:
237                 len = print_parent_column(qgroup);
238                 print_qgroup_column_add_blank(BTRFS_QGROUP_PARENT, len);
239                 break;
240         case BTRFS_QGROUP_MAX_RFER:
241                 if (qgroup->flags & BTRFS_QGROUP_LIMIT_MAX_RFER)
242                         len = printf("%*s", max_len, pretty_size_mode(qgroup->max_rfer, unit_mode));
243                 else
244                         len = printf("%*s", max_len, "none");
245                 break;
246         case BTRFS_QGROUP_MAX_EXCL:
247                 if (qgroup->flags & BTRFS_QGROUP_LIMIT_MAX_EXCL)
248                         len = printf("%*s", max_len, pretty_size_mode(qgroup->max_excl, unit_mode));
249                 else
250                         len = printf("%*s", max_len, "none");
251                 break;
252         case BTRFS_QGROUP_CHILD:
253                 len = print_child_column(qgroup);
254                 print_qgroup_column_add_blank(BTRFS_QGROUP_CHILD, len);
255                 break;
256         default:
257                 break;
258         }
259 }
260
261 static void print_single_qgroup_table(struct btrfs_qgroup *qgroup)
262 {
263         int i;
264
265         for (i = 0; i < BTRFS_QGROUP_ALL; i++) {
266                 if (!btrfs_qgroup_columns[i].need_print)
267                         continue;
268                 print_qgroup_column(qgroup, i);
269
270                 if (i != BTRFS_QGROUP_CHILD)
271                         printf(" ");
272         }
273         printf("\n");
274 }
275
276 static void print_table_head(void)
277 {
278         int i;
279         int len;
280         int max_len;
281
282         for (i = 0; i < BTRFS_QGROUP_ALL; i++) {
283                 max_len = btrfs_qgroup_columns[i].max_len;
284                 if (!btrfs_qgroup_columns[i].need_print)
285                         continue;
286                 if ((i == BTRFS_QGROUP_QGROUPID) | (i == BTRFS_QGROUP_PARENT) |
287                         (i == BTRFS_QGROUP_CHILD))
288                         printf("%-*s", max_len, btrfs_qgroup_columns[i].name);
289                 else
290                         printf("%*s", max_len, btrfs_qgroup_columns[i].name);
291                 printf(" ");
292         }
293         printf("\n");
294         for (i = 0; i < BTRFS_QGROUP_ALL; i++) {
295                 max_len = btrfs_qgroup_columns[i].max_len;
296                 if (!btrfs_qgroup_columns[i].need_print)
297                         continue;
298                 if ((i == BTRFS_QGROUP_QGROUPID) | (i == BTRFS_QGROUP_PARENT) |
299                         (i == BTRFS_QGROUP_CHILD)) {
300                         len = strlen(btrfs_qgroup_columns[i].name);
301                         while (len--)
302                                 printf("-");
303                         len = max_len - strlen(btrfs_qgroup_columns[i].name);
304                         while (len--)
305                                 printf(" ");
306                 } else {
307                         len = max_len - strlen(btrfs_qgroup_columns[i].name);
308                         while (len--)
309                                 printf(" ");
310                         len = strlen(btrfs_qgroup_columns[i].name);
311                         while (len--)
312                                 printf("-");
313                 }
314                 printf(" ");
315         }
316         printf("\n");
317 }
318
319 static void qgroup_lookup_init(struct qgroup_lookup *tree)
320 {
321         tree->root.rb_node = NULL;
322 }
323
324 static int comp_entry_with_qgroupid(struct btrfs_qgroup *entry1,
325                                     struct btrfs_qgroup *entry2,
326                                     int is_descending)
327 {
328
329         int ret;
330
331         if (entry1->qgroupid > entry2->qgroupid)
332                 ret = 1;
333         else if (entry1->qgroupid < entry2->qgroupid)
334                 ret = -1;
335         else
336                 ret = 0;
337
338         return is_descending ? -ret : ret;
339 }
340
341 static int comp_entry_with_rfer(struct btrfs_qgroup *entry1,
342                                 struct btrfs_qgroup *entry2,
343                                 int is_descending)
344 {
345         int ret;
346
347         if (entry1->rfer > entry2->rfer)
348                 ret = 1;
349         else if (entry1->rfer < entry2->rfer)
350                 ret = -1;
351         else
352                 ret = 0;
353
354         return is_descending ? -ret : ret;
355 }
356
357 static int comp_entry_with_excl(struct btrfs_qgroup *entry1,
358                                 struct btrfs_qgroup *entry2,
359                                 int is_descending)
360 {
361         int ret;
362
363         if (entry1->excl > entry2->excl)
364                 ret = 1;
365         else if (entry1->excl < entry2->excl)
366                 ret = -1;
367         else
368                 ret = 0;
369
370         return is_descending ? -ret : ret;
371 }
372
373 static int comp_entry_with_max_rfer(struct btrfs_qgroup *entry1,
374                                     struct btrfs_qgroup *entry2,
375                                     int is_descending)
376 {
377         int ret;
378
379         if (entry1->max_rfer > entry2->max_rfer)
380                 ret = 1;
381         else if (entry1->max_rfer < entry2->max_rfer)
382                 ret = -1;
383         else
384                 ret = 0;
385
386         return is_descending ? -ret : ret;
387 }
388
389 static int comp_entry_with_max_excl(struct btrfs_qgroup *entry1,
390                                     struct btrfs_qgroup *entry2,
391                                     int is_descending)
392 {
393         int ret;
394
395         if (entry1->max_excl > entry2->max_excl)
396                 ret = 1;
397         else if (entry1->max_excl < entry2->max_excl)
398                 ret = -1;
399         else
400                 ret = 0;
401
402         return is_descending ? -ret : ret;
403 }
404
405 static btrfs_qgroup_comp_func all_comp_funcs[] = {
406         [BTRFS_QGROUP_COMP_QGROUPID]    = comp_entry_with_qgroupid,
407         [BTRFS_QGROUP_COMP_RFER]        = comp_entry_with_rfer,
408         [BTRFS_QGROUP_COMP_EXCL]        = comp_entry_with_excl,
409         [BTRFS_QGROUP_COMP_MAX_RFER]    = comp_entry_with_max_rfer,
410         [BTRFS_QGROUP_COMP_MAX_EXCL]    = comp_entry_with_max_excl
411 };
412
413 static char *all_sort_items[] = {
414         [BTRFS_QGROUP_COMP_QGROUPID]    = "qgroupid",
415         [BTRFS_QGROUP_COMP_RFER]        = "rfer",
416         [BTRFS_QGROUP_COMP_EXCL]        = "excl",
417         [BTRFS_QGROUP_COMP_MAX_RFER]    = "max_rfer",
418         [BTRFS_QGROUP_COMP_MAX_EXCL]    = "max_excl",
419         [BTRFS_QGROUP_COMP_MAX]         = NULL,
420 };
421
422 static int  btrfs_qgroup_get_sort_item(char *sort_name)
423 {
424         int i;
425
426         for (i = 0; i < BTRFS_QGROUP_COMP_MAX; i++) {
427                 if (strcmp(sort_name, all_sort_items[i]) == 0)
428                         return i;
429         }
430         return -1;
431 }
432
433 struct btrfs_qgroup_comparer_set *btrfs_qgroup_alloc_comparer_set(void)
434 {
435         struct btrfs_qgroup_comparer_set *set;
436         int size;
437         size = sizeof(struct btrfs_qgroup_comparer_set) +
438                BTRFS_QGROUP_NCOMPS_INCREASE *
439                sizeof(struct btrfs_qgroup_comparer);
440         set = calloc(1, size);
441         if (!set) {
442                 error("memory allocation failed");
443                 exit(1);
444         }
445
446         set->total = BTRFS_QGROUP_NCOMPS_INCREASE;
447
448         return set;
449 }
450
451 int btrfs_qgroup_setup_comparer(struct btrfs_qgroup_comparer_set  **comp_set,
452                                 enum btrfs_qgroup_comp_enum comparer,
453                                 int is_descending)
454 {
455         struct btrfs_qgroup_comparer_set *set = *comp_set;
456         int size;
457
458         ASSERT(set != NULL);
459         ASSERT(comparer < BTRFS_QGROUP_COMP_MAX);
460         ASSERT(set->ncomps <= set->total);
461
462         if (set->ncomps == set->total) {
463                 void *tmp;
464
465                 size = set->total + BTRFS_QGROUP_NCOMPS_INCREASE;
466                 size = sizeof(*set) +
467                        size * sizeof(struct btrfs_qgroup_comparer);
468                 tmp = set;
469                 set = realloc(set, size);
470                 if (!set) {
471                         error("memory allocation failed");
472                         free(tmp);
473                         exit(1);
474                 }
475
476                 memset(&set->comps[set->total], 0,
477                        BTRFS_QGROUP_NCOMPS_INCREASE *
478                        sizeof(struct btrfs_qgroup_comparer));
479                 set->total += BTRFS_QGROUP_NCOMPS_INCREASE;
480                 *comp_set = set;
481         }
482
483         ASSERT(set->comps[set->ncomps].comp_func == NULL);
484
485         set->comps[set->ncomps].comp_func = all_comp_funcs[comparer];
486         set->comps[set->ncomps].is_descending = is_descending;
487         set->ncomps++;
488         return 0;
489 }
490
491 static int sort_comp(struct btrfs_qgroup *entry1, struct btrfs_qgroup *entry2,
492                      struct btrfs_qgroup_comparer_set *set)
493 {
494         int qgroupid_compared = 0;
495         int i, ret = 0;
496
497         if (!set || !set->ncomps)
498                 goto comp_qgroupid;
499
500         for (i = 0; i < set->ncomps; i++) {
501                 if (!set->comps[i].comp_func)
502                         break;
503
504                 ret = set->comps[i].comp_func(entry1, entry2,
505                                               set->comps[i].is_descending);
506                 if (ret)
507                         return ret;
508
509                 if (set->comps[i].comp_func == comp_entry_with_qgroupid)
510                         qgroupid_compared = 1;
511         }
512
513         if (!qgroupid_compared) {
514 comp_qgroupid:
515                 ret = comp_entry_with_qgroupid(entry1, entry2, 0);
516         }
517
518         return ret;
519 }
520
521 /*
522  * insert a new root into the tree.  returns the existing root entry
523  * if one is already there.  qgroupid is used
524  * as the key
525  */
526 static int qgroup_tree_insert(struct qgroup_lookup *root_tree,
527                               struct btrfs_qgroup *ins)
528 {
529
530         struct rb_node **p = &root_tree->root.rb_node;
531         struct rb_node *parent = NULL;
532         struct btrfs_qgroup *curr;
533         int ret;
534
535         while (*p) {
536                 parent = *p;
537                 curr = rb_entry(parent, struct btrfs_qgroup, rb_node);
538
539                 ret = comp_entry_with_qgroupid(ins, curr, 0);
540                 if (ret < 0)
541                         p = &(*p)->rb_left;
542                 else if (ret > 0)
543                         p = &(*p)->rb_right;
544                 else
545                         return -EEXIST;
546         }
547         rb_link_node(&ins->rb_node, parent, p);
548         rb_insert_color(&ins->rb_node, &root_tree->root);
549         return 0;
550 }
551
552 /*
553  *find a given qgroupid in the tree. We return the smallest one,
554  *rb_next can be used to move forward looking for more if required
555  */
556 static struct btrfs_qgroup *qgroup_tree_search(struct qgroup_lookup *root_tree,
557                                                u64 qgroupid)
558 {
559         struct rb_node *n = root_tree->root.rb_node;
560         struct btrfs_qgroup *entry;
561         struct btrfs_qgroup tmp;
562         int ret;
563
564         tmp.qgroupid = qgroupid;
565
566         while (n) {
567                 entry = rb_entry(n, struct btrfs_qgroup, rb_node);
568
569                 ret = comp_entry_with_qgroupid(&tmp, entry, 0);
570                 if (ret < 0)
571                         n = n->rb_left;
572                 else if (ret > 0)
573                         n = n->rb_right;
574                 else
575                         return entry;
576
577         }
578         return NULL;
579 }
580
581 /*
582  * Lookup or insert btrfs_qgroup into qgroup_lookup.
583  *
584  * Search a btrfs_qgroup with @qgroupid from the @qgroup_lookup. If not found,
585  * initialize a btrfs_qgroup with the given qgroupid and insert it to the
586  * @qgroup_lookup.
587  *
588  * Return the pointer to the btrfs_qgroup if found or if inserted successfully.
589  * Return ERR_PTR if any error occurred.
590  */
591 static struct btrfs_qgroup *get_or_add_qgroup(
592                 struct qgroup_lookup *qgroup_lookup, u64 qgroupid)
593 {
594         struct btrfs_qgroup *bq;
595         int ret;
596
597         bq = qgroup_tree_search(qgroup_lookup, qgroupid);
598         if (bq)
599                 return bq;
600
601         bq = calloc(1, sizeof(*bq));
602         if (!bq) {
603                 error("memory allocation failed");
604                 return ERR_PTR(-ENOMEM);
605         }
606
607         bq->qgroupid = qgroupid;
608         INIT_LIST_HEAD(&bq->qgroups);
609         INIT_LIST_HEAD(&bq->members);
610
611         ret = qgroup_tree_insert(qgroup_lookup, bq);
612         if (ret) {
613                 error("failed to insert %llu into tree: %s",
614                        (unsigned long long)bq->qgroupid, strerror(-ret));
615                 free(bq);
616                 return ERR_PTR(ret);
617         }
618
619         return bq;
620 }
621
622 static int update_qgroup_info(struct qgroup_lookup *qgroup_lookup, u64 qgroupid,
623                               struct btrfs_qgroup_info_item *info)
624 {
625         struct btrfs_qgroup *bq;
626
627         bq = get_or_add_qgroup(qgroup_lookup, qgroupid);
628         if (IS_ERR_OR_NULL(bq))
629                 return PTR_ERR(bq);
630
631         bq->generation = btrfs_stack_qgroup_info_generation(info);
632         bq->rfer = btrfs_stack_qgroup_info_referenced(info);
633         bq->rfer_cmpr = btrfs_stack_qgroup_info_referenced_compressed(info);
634         bq->excl = btrfs_stack_qgroup_info_exclusive(info);
635         bq->excl_cmpr = btrfs_stack_qgroup_info_exclusive_compressed(info);
636
637         return 0;
638 }
639
640 static int update_qgroup_limit(struct qgroup_lookup *qgroup_lookup,
641                                u64 qgroupid,
642                                struct btrfs_qgroup_limit_item *limit)
643 {
644         struct btrfs_qgroup *bq;
645
646         bq = get_or_add_qgroup(qgroup_lookup, qgroupid);
647         if (IS_ERR_OR_NULL(bq))
648                 return PTR_ERR(bq);
649
650         bq->flags = btrfs_stack_qgroup_limit_flags(limit);
651         bq->max_rfer = btrfs_stack_qgroup_limit_max_referenced(limit);
652         bq->max_excl = btrfs_stack_qgroup_limit_max_exclusive(limit);
653         bq->rsv_rfer = btrfs_stack_qgroup_limit_rsv_referenced(limit);
654         bq->rsv_excl = btrfs_stack_qgroup_limit_rsv_exclusive(limit);
655
656         return 0;
657 }
658
659 static int update_qgroup_relation(struct qgroup_lookup *qgroup_lookup,
660                                   u64 child_id, u64 parent_id)
661 {
662         struct btrfs_qgroup *child;
663         struct btrfs_qgroup *parent;
664         struct btrfs_qgroup_list *list;
665
666         child = qgroup_tree_search(qgroup_lookup, child_id);
667         if (!child) {
668                 error("cannot find the qgroup %llu/%llu",
669                       btrfs_qgroup_level(child_id),
670                       btrfs_qgroup_subvid(child_id));
671                 return -ENOENT;
672         }
673
674         parent = qgroup_tree_search(qgroup_lookup, parent_id);
675         if (!parent) {
676                 error("cannot find the qgroup %llu/%llu",
677                       btrfs_qgroup_level(parent_id),
678                       btrfs_qgroup_subvid(parent_id));
679                 return -ENOENT;
680         }
681
682         list = malloc(sizeof(*list));
683         if (!list) {
684                 error("memory allocation failed");
685                 return -ENOMEM;
686         }
687
688         list->qgroup = parent;
689         list->member = child;
690         list_add_tail(&list->next_qgroup, &child->qgroups);
691         list_add_tail(&list->next_member, &parent->members);
692
693         return 0;
694 }
695
696 static void __free_btrfs_qgroup(struct btrfs_qgroup *bq)
697 {
698         struct btrfs_qgroup_list *list;
699         while (!list_empty(&bq->qgroups)) {
700                 list = list_entry((&bq->qgroups)->next,
701                                   struct btrfs_qgroup_list,
702                                   next_qgroup);
703                 list_del(&list->next_qgroup);
704                 list_del(&list->next_member);
705                 free(list);
706         }
707         while (!list_empty(&bq->members)) {
708                 list = list_entry((&bq->members)->next,
709                                   struct btrfs_qgroup_list,
710                                   next_member);
711                 list_del(&list->next_qgroup);
712                 list_del(&list->next_member);
713                 free(list);
714         }
715         free(bq);
716 }
717
718 static void __free_all_qgroups(struct qgroup_lookup *root_tree)
719 {
720         struct btrfs_qgroup *entry;
721         struct rb_node *n;
722
723         n = rb_first(&root_tree->root);
724         while (n) {
725                 entry = rb_entry(n, struct btrfs_qgroup, rb_node);
726                 rb_erase(n, &root_tree->root);
727                 __free_btrfs_qgroup(entry);
728
729                 n = rb_first(&root_tree->root);
730         }
731 }
732
733 static int filter_all_parent_insert(struct qgroup_lookup *sort_tree,
734                                     struct btrfs_qgroup *bq)
735 {
736         struct rb_node **p = &sort_tree->root.rb_node;
737         struct rb_node *parent = NULL;
738         struct btrfs_qgroup *curr;
739         int ret;
740
741         while (*p) {
742                 parent = *p;
743                 curr = rb_entry(parent, struct btrfs_qgroup, all_parent_node);
744
745                 ret = comp_entry_with_qgroupid(bq, curr, 0);
746                 if (ret < 0)
747                         p = &(*p)->rb_left;
748                 else if (ret > 0)
749                         p = &(*p)->rb_right;
750                 else
751                         return -EEXIST;
752         }
753         rb_link_node(&bq->all_parent_node, parent, p);
754         rb_insert_color(&bq->all_parent_node, &sort_tree->root);
755         return 0;
756 }
757
758 static int filter_by_parent(struct btrfs_qgroup *bq, u64 data)
759 {
760         struct btrfs_qgroup *qgroup =
761                 (struct btrfs_qgroup *)(unsigned long)data;
762
763         if (data == 0)
764                 return 0;
765         if (qgroup->qgroupid == bq->qgroupid)
766                 return 1;
767         return 0;
768 }
769
770 static int filter_by_all_parent(struct btrfs_qgroup *bq, u64 data)
771 {
772         struct qgroup_lookup lookup;
773         struct qgroup_lookup *ql = &lookup;
774         struct btrfs_qgroup_list *list;
775         struct rb_node *n;
776         struct btrfs_qgroup *qgroup =
777                          (struct btrfs_qgroup *)(unsigned long)data;
778
779         if (data == 0)
780                 return 0;
781         if (bq->qgroupid == qgroup->qgroupid)
782                 return 1;
783
784         qgroup_lookup_init(ql);
785         filter_all_parent_insert(ql, qgroup);
786         n = rb_first(&ql->root);
787         while (n) {
788                 qgroup = rb_entry(n, struct btrfs_qgroup, all_parent_node);
789                 if (!list_empty(&qgroup->qgroups)) {
790                         list_for_each_entry(list, &qgroup->qgroups,
791                                             next_qgroup) {
792                                 if ((list->qgroup)->qgroupid == bq->qgroupid)
793                                         return 1;
794                                 filter_all_parent_insert(ql, list->qgroup);
795                         }
796                 }
797                 rb_erase(n, &ql->root);
798                 n = rb_first(&ql->root);
799         }
800         return 0;
801 }
802
803 static btrfs_qgroup_filter_func all_filter_funcs[] = {
804         [BTRFS_QGROUP_FILTER_PARENT]            = filter_by_parent,
805         [BTRFS_QGROUP_FILTER_ALL_PARENT]        = filter_by_all_parent,
806 };
807
808 struct btrfs_qgroup_filter_set *btrfs_qgroup_alloc_filter_set(void)
809 {
810         struct btrfs_qgroup_filter_set *set;
811         int size;
812
813         size = sizeof(struct btrfs_qgroup_filter_set) +
814                BTRFS_QGROUP_NFILTERS_INCREASE *
815                sizeof(struct btrfs_qgroup_filter);
816         set = calloc(1, size);
817         if (!set) {
818                 error("memory allocation failed");
819                 exit(1);
820         }
821         set->total = BTRFS_QGROUP_NFILTERS_INCREASE;
822
823         return set;
824 }
825
826 int btrfs_qgroup_setup_filter(struct btrfs_qgroup_filter_set **filter_set,
827                               enum btrfs_qgroup_filter_enum filter, u64 data)
828 {
829         struct btrfs_qgroup_filter_set *set = *filter_set;
830         int size;
831
832         ASSERT(set != NULL);
833         ASSERT(filter < BTRFS_QGROUP_FILTER_MAX);
834         ASSERT(set->nfilters <= set->total);
835
836         if (set->nfilters == set->total) {
837                 void *tmp;
838
839                 size = set->total + BTRFS_QGROUP_NFILTERS_INCREASE;
840                 size = sizeof(*set) + size * sizeof(struct btrfs_qgroup_filter);
841
842                 tmp = set;
843                 set = realloc(set, size);
844                 if (!set) {
845                         error("memory allocation failed");
846                         free(tmp);
847                         exit(1);
848                 }
849                 memset(&set->filters[set->total], 0,
850                        BTRFS_QGROUP_NFILTERS_INCREASE *
851                        sizeof(struct btrfs_qgroup_filter));
852                 set->total += BTRFS_QGROUP_NFILTERS_INCREASE;
853                 *filter_set = set;
854         }
855
856         ASSERT(set->filters[set->nfilters].filter_func == NULL);
857         set->filters[set->nfilters].filter_func = all_filter_funcs[filter];
858         set->filters[set->nfilters].data = data;
859         set->nfilters++;
860         return 0;
861 }
862
863 static int filter_qgroup(struct btrfs_qgroup *bq,
864                          struct btrfs_qgroup_filter_set *set)
865 {
866         int i, ret;
867
868         if (!set || !set->nfilters)
869                 return 1;
870         for (i = 0; i < set->nfilters; i++) {
871                 if (!set->filters[i].filter_func)
872                         break;
873                 ret = set->filters[i].filter_func(bq, set->filters[i].data);
874                 if (!ret)
875                         return 0;
876         }
877         return 1;
878 }
879
880 static void pre_process_filter_set(struct qgroup_lookup *lookup,
881                                    struct btrfs_qgroup_filter_set *set)
882 {
883         int i;
884         struct btrfs_qgroup *qgroup_for_filter = NULL;
885
886         for (i = 0; i < set->nfilters; i++) {
887
888                 if (set->filters[i].filter_func == filter_by_all_parent
889                     || set->filters[i].filter_func == filter_by_parent) {
890                         qgroup_for_filter = qgroup_tree_search(lookup,
891                                             set->filters[i].data);
892                         set->filters[i].data =
893                                  (u64)(unsigned long)qgroup_for_filter;
894                 }
895         }
896 }
897
898 static int sort_tree_insert(struct qgroup_lookup *sort_tree,
899                             struct btrfs_qgroup *bq,
900                             struct btrfs_qgroup_comparer_set *comp_set)
901 {
902         struct rb_node **p = &sort_tree->root.rb_node;
903         struct rb_node *parent = NULL;
904         struct btrfs_qgroup *curr;
905         int ret;
906
907         while (*p) {
908                 parent = *p;
909                 curr = rb_entry(parent, struct btrfs_qgroup, sort_node);
910
911                 ret = sort_comp(bq, curr, comp_set);
912                 if (ret < 0)
913                         p = &(*p)->rb_left;
914                 else if (ret > 0)
915                         p = &(*p)->rb_right;
916                 else
917                         return -EEXIST;
918         }
919         rb_link_node(&bq->sort_node, parent, p);
920         rb_insert_color(&bq->sort_node, &sort_tree->root);
921         return 0;
922 }
923
924 static void __update_columns_max_len(struct btrfs_qgroup *bq,
925                                      enum btrfs_qgroup_column_enum column)
926 {
927         struct btrfs_qgroup_list *list = NULL;
928         char tmp[100];
929         int len;
930         unsigned unit_mode = btrfs_qgroup_columns[column].unit_mode;
931
932         ASSERT(0 <= column && column < BTRFS_QGROUP_ALL);
933
934         switch (column) {
935
936         case BTRFS_QGROUP_QGROUPID:
937                 sprintf(tmp, "%llu/%llu",
938                         btrfs_qgroup_level(bq->qgroupid),
939                         btrfs_qgroup_subvid(bq->qgroupid));
940                 len = strlen(tmp);
941                 if (btrfs_qgroup_columns[column].max_len < len)
942                         btrfs_qgroup_columns[column].max_len = len;
943                 break;
944         case BTRFS_QGROUP_RFER:
945                 len = strlen(pretty_size_mode(bq->rfer, unit_mode));
946                 if (btrfs_qgroup_columns[column].max_len < len)
947                         btrfs_qgroup_columns[column].max_len = len;
948                 break;
949         case BTRFS_QGROUP_EXCL:
950                 len = strlen(pretty_size_mode(bq->excl, unit_mode));
951                 if (btrfs_qgroup_columns[column].max_len < len)
952                         btrfs_qgroup_columns[column].max_len = len;
953                 break;
954         case BTRFS_QGROUP_MAX_RFER:
955                 len = strlen(pretty_size_mode(bq->max_rfer, unit_mode));
956                 if (btrfs_qgroup_columns[column].max_len < len)
957                         btrfs_qgroup_columns[column].max_len = len;
958                 break;
959         case BTRFS_QGROUP_MAX_EXCL:
960                 len = strlen(pretty_size_mode(bq->max_excl, unit_mode));
961                 if (btrfs_qgroup_columns[column].max_len < len)
962                         btrfs_qgroup_columns[column].max_len = len;
963                 break;
964         case BTRFS_QGROUP_PARENT:
965                 len = 0;
966                 list_for_each_entry(list, &bq->qgroups, next_qgroup) {
967                         len += sprintf(tmp, "%llu/%llu",
968                                 btrfs_qgroup_level(list->qgroup->qgroupid),
969                                 btrfs_qgroup_subvid(list->qgroup->qgroupid));
970                         if (!list_is_last(&list->next_qgroup, &bq->qgroups))
971                                 len += 1;
972                 }
973                 if (btrfs_qgroup_columns[column].max_len < len)
974                         btrfs_qgroup_columns[column].max_len = len;
975                 break;
976         case BTRFS_QGROUP_CHILD:
977                 len = 0;
978                 list_for_each_entry(list, &bq->members, next_member) {
979                         len += sprintf(tmp, "%llu/%llu",
980                                 btrfs_qgroup_level(list->member->qgroupid),
981                                 btrfs_qgroup_subvid(list->member->qgroupid));
982                         if (!list_is_last(&list->next_member, &bq->members))
983                                 len += 1;
984                 }
985                 if (btrfs_qgroup_columns[column].max_len < len)
986                         btrfs_qgroup_columns[column].max_len = len;
987                 break;
988         default:
989                 break;
990         }
991
992 }
993
994 static void update_columns_max_len(struct btrfs_qgroup *bq)
995 {
996         int i;
997
998         for (i = 0; i < BTRFS_QGROUP_ALL; i++) {
999                 if (!btrfs_qgroup_columns[i].need_print)
1000                         continue;
1001                 __update_columns_max_len(bq, i);
1002         }
1003 }
1004
1005 static void __filter_and_sort_qgroups(struct qgroup_lookup *all_qgroups,
1006                                  struct qgroup_lookup *sort_tree,
1007                                  struct btrfs_qgroup_filter_set *filter_set,
1008                                  struct btrfs_qgroup_comparer_set *comp_set)
1009 {
1010         struct rb_node *n;
1011         struct btrfs_qgroup *entry;
1012         int ret;
1013
1014         qgroup_lookup_init(sort_tree);
1015         pre_process_filter_set(all_qgroups, filter_set);
1016
1017         n = rb_last(&all_qgroups->root);
1018         while (n) {
1019                 entry = rb_entry(n, struct btrfs_qgroup, rb_node);
1020
1021                 ret = filter_qgroup(entry, filter_set);
1022                 if (ret) {
1023                         sort_tree_insert(sort_tree, entry, comp_set);
1024
1025                         update_columns_max_len(entry);
1026                 }
1027                 n = rb_prev(n);
1028         }
1029 }
1030
1031 static inline void print_status_flag_warning(u64 flags)
1032 {
1033         if (!(flags & BTRFS_QGROUP_STATUS_FLAG_ON))
1034                 warning("quota disabled, qgroup data may be out of date");
1035         else if (flags & BTRFS_QGROUP_STATUS_FLAG_RESCAN)
1036                 warning("rescan is running, qgroup data may be incorrect");
1037         else if (flags & BTRFS_QGROUP_STATUS_FLAG_INCONSISTENT)
1038                 warning("qgroup data inconsistent, rescan recommended");
1039 }
1040
1041 static int __qgroups_search(int fd, struct qgroup_lookup *qgroup_lookup)
1042 {
1043         int ret;
1044         struct btrfs_ioctl_search_args args;
1045         struct btrfs_ioctl_search_key *sk = &args.key;
1046         struct btrfs_ioctl_search_header *sh;
1047         unsigned long off = 0;
1048         unsigned int i;
1049         struct btrfs_qgroup_status_item *si;
1050         struct btrfs_qgroup_info_item *info;
1051         struct btrfs_qgroup_limit_item *limit;
1052         u64 flags;
1053         u64 qgroupid;
1054         u64 qgroupid1;
1055
1056         memset(&args, 0, sizeof(args));
1057
1058         sk->tree_id = BTRFS_QUOTA_TREE_OBJECTID;
1059         sk->max_type = BTRFS_QGROUP_RELATION_KEY;
1060         sk->min_type = BTRFS_QGROUP_STATUS_KEY;
1061         sk->max_objectid = (u64)-1;
1062         sk->max_offset = (u64)-1;
1063         sk->max_transid = (u64)-1;
1064         sk->nr_items = 4096;
1065
1066         qgroup_lookup_init(qgroup_lookup);
1067
1068         while (1) {
1069                 ret = ioctl(fd, BTRFS_IOC_TREE_SEARCH, &args);
1070                 if (ret < 0) {
1071                         if (errno == ENOENT) {
1072                                 error("can't list qgroups: quotas not enabled");
1073                                 ret = -ENOTTY;
1074                         } else {
1075                                 error("can't list qgroups: %s",
1076                                        strerror(errno));
1077                                 ret = -errno;
1078                         }
1079
1080                         break;
1081                 }
1082
1083                 /* the ioctl returns the number of item it found in nr_items */
1084                 if (sk->nr_items == 0)
1085                         break;
1086
1087                 off = 0;
1088                 /*
1089                  * for each item, pull the key out of the header and then
1090                  * read the root_ref item it contains
1091                  */
1092                 for (i = 0; i < sk->nr_items; i++) {
1093                         sh = (struct btrfs_ioctl_search_header *)(args.buf +
1094                                                                   off);
1095                         off += sizeof(*sh);
1096
1097                         switch (btrfs_search_header_type(sh)) {
1098                         case BTRFS_QGROUP_STATUS_KEY:
1099                                 si = (struct btrfs_qgroup_status_item *)
1100                                      (args.buf + off);
1101                                 flags = btrfs_stack_qgroup_status_flags(si);
1102
1103                                 print_status_flag_warning(flags);
1104                                 break;
1105                         case BTRFS_QGROUP_INFO_KEY:
1106                                 qgroupid = btrfs_search_header_offset(sh);
1107                                 info = (struct btrfs_qgroup_info_item *)
1108                                        (args.buf + off);
1109
1110                                 ret = update_qgroup_info(qgroup_lookup,
1111                                                          qgroupid, info);
1112                                 break;
1113                         case BTRFS_QGROUP_LIMIT_KEY:
1114                                 qgroupid = btrfs_search_header_offset(sh);
1115                                 limit = (struct btrfs_qgroup_limit_item *)
1116                                         (args.buf + off);
1117
1118                                 ret = update_qgroup_limit(qgroup_lookup,
1119                                                           qgroupid, limit);
1120                                 break;
1121                         case BTRFS_QGROUP_RELATION_KEY:
1122                                 qgroupid = btrfs_search_header_offset(sh);
1123                                 qgroupid1 = btrfs_search_header_objectid(sh);
1124
1125                                 if (qgroupid < qgroupid1)
1126                                         break;
1127
1128                                 ret = update_qgroup_relation(qgroup_lookup,
1129                                                         qgroupid, qgroupid1);
1130                                 break;
1131                         default:
1132                                 return ret;
1133                         }
1134
1135                         if (ret)
1136                                 return ret;
1137
1138                         off += btrfs_search_header_len(sh);
1139
1140                         /*
1141                          * record the mins in sk so we can make sure the
1142                          * next search doesn't repeat this root
1143                          */
1144                         sk->min_type = btrfs_search_header_type(sh);
1145                         sk->min_offset = btrfs_search_header_offset(sh);
1146                         sk->min_objectid = btrfs_search_header_objectid(sh);
1147                 }
1148                 sk->nr_items = 4096;
1149                 /*
1150                  * this iteration is done, step forward one qgroup for the next
1151                  * ioctl
1152                  */
1153                 if (sk->min_offset < (u64)-1)
1154                         sk->min_offset++;
1155                 else
1156                         break;
1157         }
1158
1159         return ret;
1160 }
1161
1162 static void print_all_qgroups(struct qgroup_lookup *qgroup_lookup)
1163 {
1164
1165         struct rb_node *n;
1166         struct btrfs_qgroup *entry;
1167
1168         print_table_head();
1169
1170         n = rb_first(&qgroup_lookup->root);
1171         while (n) {
1172                 entry = rb_entry(n, struct btrfs_qgroup, sort_node);
1173                 print_single_qgroup_table(entry);
1174                 n = rb_next(n);
1175         }
1176 }
1177
1178 int btrfs_show_qgroups(int fd,
1179                        struct btrfs_qgroup_filter_set *filter_set,
1180                        struct btrfs_qgroup_comparer_set *comp_set)
1181 {
1182
1183         struct qgroup_lookup qgroup_lookup;
1184         struct qgroup_lookup sort_tree;
1185         int ret;
1186
1187         ret = __qgroups_search(fd, &qgroup_lookup);
1188         if (ret)
1189                 return ret;
1190         __filter_and_sort_qgroups(&qgroup_lookup, &sort_tree,
1191                                   filter_set, comp_set);
1192         print_all_qgroups(&sort_tree);
1193
1194         __free_all_qgroups(&qgroup_lookup);
1195         return ret;
1196 }
1197
1198 int btrfs_qgroup_parse_sort_string(const char *opt_arg,
1199                                    struct btrfs_qgroup_comparer_set **comps)
1200 {
1201         int order;
1202         int flag;
1203         char *p;
1204         char **ptr_argv;
1205         int what_to_sort;
1206         char *opt_tmp;
1207         int ret = 0;
1208
1209         opt_tmp = strdup(opt_arg);
1210         if (!opt_tmp)
1211                 return -ENOMEM;
1212
1213         p = strtok(opt_tmp, ",");
1214         while (p) {
1215                 flag = 0;
1216                 ptr_argv = all_sort_items;
1217
1218                 while (*ptr_argv) {
1219                         if (strcmp(*ptr_argv, p) == 0) {
1220                                 flag = 1;
1221                                 break;
1222                         } else {
1223                                 p++;
1224                                 if (strcmp(*ptr_argv, p) == 0) {
1225                                         flag = 1;
1226                                         p--;
1227                                         break;
1228                                 }
1229                                 p--;
1230                         }
1231                         ptr_argv++;
1232                 }
1233
1234                 if (flag == 0) {
1235                         ret = -1;
1236                         goto out;
1237                 } else {
1238                         if (*p == '+') {
1239                                 order = 0;
1240                                 p++;
1241                         } else if (*p == '-') {
1242                                 order = 1;
1243                                 p++;
1244                         } else
1245                                 order = 0;
1246
1247                         what_to_sort = btrfs_qgroup_get_sort_item(p);
1248                         if (what_to_sort < 0) {
1249                                 ret = -1;
1250                                 goto out;
1251                         }
1252                         btrfs_qgroup_setup_comparer(comps, what_to_sort, order);
1253                 }
1254                 p = strtok(NULL, ",");
1255         }
1256
1257 out:
1258         free(opt_tmp);
1259         return ret;
1260 }
1261
1262 int qgroup_inherit_size(struct btrfs_qgroup_inherit *p)
1263 {
1264         return sizeof(*p) + sizeof(p->qgroups[0]) *
1265                             (p->num_qgroups + 2 * p->num_ref_copies +
1266                              2 * p->num_excl_copies);
1267 }
1268
1269 static int
1270 qgroup_inherit_realloc(struct btrfs_qgroup_inherit **inherit, int n, int pos)
1271 {
1272         struct btrfs_qgroup_inherit *out;
1273         int nitems = 0;
1274
1275         if (*inherit) {
1276                 nitems = (*inherit)->num_qgroups +
1277                          (*inherit)->num_ref_copies +
1278                          (*inherit)->num_excl_copies;
1279         }
1280
1281         out = calloc(sizeof(*out) + sizeof(out->qgroups[0]) * (nitems + n), 1);
1282         if (out == NULL) {
1283                 error("not enough memory");
1284                 return -ENOMEM;
1285         }
1286
1287         if (*inherit) {
1288                 struct btrfs_qgroup_inherit *i = *inherit;
1289                 int s = sizeof(out->qgroups[0]);
1290
1291                 out->num_qgroups = i->num_qgroups;
1292                 out->num_ref_copies = i->num_ref_copies;
1293                 out->num_excl_copies = i->num_excl_copies;
1294                 memcpy(out->qgroups, i->qgroups, pos * s);
1295                 memcpy(out->qgroups + pos + n, i->qgroups + pos,
1296                        (nitems - pos) * s);
1297         }
1298         free(*inherit);
1299         *inherit = out;
1300
1301         return 0;
1302 }
1303
1304 int qgroup_inherit_add_group(struct btrfs_qgroup_inherit **inherit, char *arg)
1305 {
1306         int ret;
1307         u64 qgroupid = parse_qgroupid(arg);
1308         int pos = 0;
1309
1310         if (qgroupid == 0) {
1311                 error("invalid qgroup specification, qgroupid must not 0");
1312                 return -EINVAL;
1313         }
1314
1315         if (*inherit)
1316                 pos = (*inherit)->num_qgroups;
1317         ret = qgroup_inherit_realloc(inherit, 1, pos);
1318         if (ret)
1319                 return ret;
1320
1321         (*inherit)->qgroups[(*inherit)->num_qgroups++] = qgroupid;
1322
1323         return 0;
1324 }
1325
1326 int qgroup_inherit_add_copy(struct btrfs_qgroup_inherit **inherit, char *arg,
1327                             int type)
1328 {
1329         int ret;
1330         u64 qgroup_src;
1331         u64 qgroup_dst;
1332         char *p;
1333         int pos = 0;
1334
1335         p = strchr(arg, ':');
1336         if (!p) {
1337 bad:
1338                 error("invalid copy specification, missing separator :");
1339                 return -EINVAL;
1340         }
1341         *p = 0;
1342         qgroup_src = parse_qgroupid(arg);
1343         qgroup_dst = parse_qgroupid(p + 1);
1344         *p = ':';
1345
1346         if (!qgroup_src || !qgroup_dst)
1347                 goto bad;
1348
1349         if (*inherit)
1350                 pos = (*inherit)->num_qgroups +
1351                       (*inherit)->num_ref_copies * 2 * type;
1352
1353         ret = qgroup_inherit_realloc(inherit, 2, pos);
1354         if (ret)
1355                 return ret;
1356
1357         (*inherit)->qgroups[pos++] = qgroup_src;
1358         (*inherit)->qgroups[pos++] = qgroup_dst;
1359
1360         if (!type)
1361                 ++(*inherit)->num_ref_copies;
1362         else
1363                 ++(*inherit)->num_excl_copies;
1364
1365         return 0;
1366 }