btrfs-progs: Introduce function to fix super block total bytes
[platform/upstream/btrfs-progs.git] / cmds-subvolume.c
1 /*
2  * This program is free software; you can redistribute it and/or
3  * modify it under the terms of the GNU General Public
4  * License v2 as published by the Free Software Foundation.
5  *
6  * This program is distributed in the hope that it will be useful,
7  * but WITHOUT ANY WARRANTY; without even the implied warranty of
8  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
9  * General Public License for more details.
10  *
11  * You should have received a copy of the GNU General Public
12  * License along with this program; if not, write to the
13  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
14  * Boston, MA 021110-1307, USA.
15  */
16
17 #include <stdio.h>
18 #include <stdlib.h>
19 #include <string.h>
20 #include <unistd.h>
21 #include <sys/ioctl.h>
22 #include <errno.h>
23 #include <sys/stat.h>
24 #include <sys/vfs.h>
25 #include <libgen.h>
26 #include <limits.h>
27 #include <getopt.h>
28 #include <uuid/uuid.h>
29 #include <linux/magic.h>
30
31 #include "kerncompat.h"
32 #include "ioctl.h"
33 #include "qgroup.h"
34
35 #include "ctree.h"
36 #include "commands.h"
37 #include "utils.h"
38 #include "btrfs-list.h"
39 #include "utils.h"
40 #include "help.h"
41
42 static int is_subvolume_cleaned(int fd, u64 subvolid)
43 {
44         int ret;
45         struct btrfs_ioctl_search_args args;
46         struct btrfs_ioctl_search_key *sk = &args.key;
47
48         sk->tree_id = BTRFS_ROOT_TREE_OBJECTID;
49         sk->min_objectid = subvolid;
50         sk->max_objectid = subvolid;
51         sk->min_type = BTRFS_ROOT_ITEM_KEY;
52         sk->max_type = BTRFS_ROOT_ITEM_KEY;
53         sk->min_offset = 0;
54         sk->max_offset = (u64)-1;
55         sk->min_transid = 0;
56         sk->max_transid = (u64)-1;
57         sk->nr_items = 1;
58
59         ret = ioctl(fd, BTRFS_IOC_TREE_SEARCH, &args);
60         if (ret < 0)
61                 return -errno;
62
63         if (sk->nr_items == 0)
64                 return 1;
65
66         return 0;
67 }
68
69 static int wait_for_subvolume_cleaning(int fd, int count, u64 *ids,
70                 int sleep_interval)
71 {
72         int ret;
73         int i;
74
75         while (1) {
76                 int clean = 1;
77
78                 for (i = 0; i < count; i++) {
79                         if (!ids[i])
80                                 continue;
81                         ret = is_subvolume_cleaned(fd, ids[i]);
82                         if (ret < 0) {
83                                 error(
84                             "cannot read status of dead subvolume %llu: %s",
85                                         (unsigned long long)ids[i], strerror(-ret));
86                                 return ret;
87                         }
88                         if (ret) {
89                                 printf("Subvolume id %llu is gone\n", ids[i]);
90                                 ids[i] = 0;
91                         } else {
92                                 clean = 0;
93                         }
94                 }
95                 if (clean)
96                         break;
97                 sleep(sleep_interval);
98         }
99
100         return 0;
101 }
102
103 static const char * const subvolume_cmd_group_usage[] = {
104         "btrfs subvolume <command> <args>",
105         NULL
106 };
107
108 static const char * const cmd_subvol_create_usage[] = {
109         "btrfs subvolume create [-i <qgroupid>] [<dest>/]<name>",
110         "Create a subvolume",
111         "Create a subvolume <name> in <dest>.  If <dest> is not given",
112         "subvolume <name> will be created in the current directory.",
113         "",
114         "-i <qgroupid>  add the newly created subvolume to a qgroup. This",
115         "               option can be given multiple times.",
116         NULL
117 };
118
119 static int cmd_subvol_create(int argc, char **argv)
120 {
121         int     retval, res, len;
122         int     fddst = -1;
123         char    *dupname = NULL;
124         char    *dupdir = NULL;
125         char    *newname;
126         char    *dstdir;
127         char    *dst;
128         struct btrfs_qgroup_inherit *inherit = NULL;
129         DIR     *dirstream = NULL;
130
131         while (1) {
132                 int c = getopt(argc, argv, "c:i:");
133                 if (c < 0)
134                         break;
135
136                 switch (c) {
137                 case 'c':
138                         res = qgroup_inherit_add_copy(&inherit, optarg, 0);
139                         if (res) {
140                                 retval = res;
141                                 goto out;
142                         }
143                         break;
144                 case 'i':
145                         res = qgroup_inherit_add_group(&inherit, optarg);
146                         if (res) {
147                                 retval = res;
148                                 goto out;
149                         }
150                         break;
151                 default:
152                         usage(cmd_subvol_create_usage);
153                 }
154         }
155
156         if (check_argc_exact(argc - optind, 1))
157                 usage(cmd_subvol_create_usage);
158
159         dst = argv[optind];
160
161         retval = 1;     /* failure */
162         res = test_isdir(dst);
163         if (res < 0 && res != -ENOENT) {
164                 error("cannot access %s: %s", dst, strerror(-res));
165                 goto out;
166         }
167         if (res >= 0) {
168                 error("target path already exists: %s", dst);
169                 goto out;
170         }
171
172         dupname = strdup(dst);
173         newname = basename(dupname);
174         dupdir = strdup(dst);
175         dstdir = dirname(dupdir);
176
177         if (!test_issubvolname(newname)) {
178                 error("invalid subvolume name: %s", newname);
179                 goto out;
180         }
181
182         len = strlen(newname);
183         if (len == 0 || len >= BTRFS_VOL_NAME_MAX) {
184                 error("subvolume name too long: %s", newname);
185                 goto out;
186         }
187
188         fddst = btrfs_open_dir(dstdir, &dirstream, 1);
189         if (fddst < 0)
190                 goto out;
191
192         printf("Create subvolume '%s/%s'\n", dstdir, newname);
193         if (inherit) {
194                 struct btrfs_ioctl_vol_args_v2  args;
195
196                 memset(&args, 0, sizeof(args));
197                 strncpy_null(args.name, newname);
198                 args.flags |= BTRFS_SUBVOL_QGROUP_INHERIT;
199                 args.size = qgroup_inherit_size(inherit);
200                 args.qgroup_inherit = inherit;
201
202                 res = ioctl(fddst, BTRFS_IOC_SUBVOL_CREATE_V2, &args);
203         } else {
204                 struct btrfs_ioctl_vol_args     args;
205
206                 memset(&args, 0, sizeof(args));
207                 strncpy_null(args.name, newname);
208
209                 res = ioctl(fddst, BTRFS_IOC_SUBVOL_CREATE, &args);
210         }
211
212         if (res < 0) {
213                 error("cannot create subvolume: %s", strerror(errno));
214                 goto out;
215         }
216
217         retval = 0;     /* success */
218 out:
219         close_file_or_dir(fddst, dirstream);
220         free(inherit);
221         free(dupname);
222         free(dupdir);
223
224         return retval;
225 }
226
227 static int wait_for_commit(int fd)
228 {
229         int ret;
230
231         ret = ioctl(fd, BTRFS_IOC_START_SYNC, NULL);
232         if (ret < 0)
233                 return ret;
234         return ioctl(fd, BTRFS_IOC_WAIT_SYNC, NULL);
235 }
236
237 static const char * const cmd_subvol_delete_usage[] = {
238         "btrfs subvolume delete [options] <subvolume> [<subvolume>...]",
239         "Delete subvolume(s)",
240         "Delete subvolumes from the filesystem. The corresponding directory",
241         "is removed instantly but the data blocks are removed later.",
242         "The deletion does not involve full commit by default due to",
243         "performance reasons (as a consequence, the subvolume may appear again",
244         "after a crash). Use one of the --commit options to wait until the",
245         "operation is safely stored on the media.",
246         "",
247         "-c|--commit-after      wait for transaction commit at the end of the operation",
248         "-C|--commit-each       wait for transaction commit after deleting each subvolume",
249         "-v|--verbose           verbose output of operations",
250         NULL
251 };
252
253 static int cmd_subvol_delete(int argc, char **argv)
254 {
255         int res, ret = 0;
256         int cnt;
257         int fd = -1;
258         struct btrfs_ioctl_vol_args     args;
259         char    *dname, *vname, *cpath;
260         char    *dupdname = NULL;
261         char    *dupvname = NULL;
262         char    *path;
263         DIR     *dirstream = NULL;
264         int verbose = 0;
265         int commit_mode = 0;
266         u8 fsid[BTRFS_FSID_SIZE];
267         char uuidbuf[BTRFS_UUID_UNPARSED_SIZE];
268         struct seen_fsid *seen_fsid_hash[SEEN_FSID_HASH_SIZE] = { NULL, };
269         enum { COMMIT_AFTER = 1, COMMIT_EACH = 2 };
270
271         while (1) {
272                 int c;
273                 static const struct option long_options[] = {
274                         {"commit-after", no_argument, NULL, 'c'},
275                         {"commit-each", no_argument, NULL, 'C'},
276                         {"verbose", no_argument, NULL, 'v'},
277                         {NULL, 0, NULL, 0}
278                 };
279
280                 c = getopt_long(argc, argv, "cCv", long_options, NULL);
281                 if (c < 0)
282                         break;
283
284                 switch(c) {
285                 case 'c':
286                         commit_mode = COMMIT_AFTER;
287                         break;
288                 case 'C':
289                         commit_mode = COMMIT_EACH;
290                         break;
291                 case 'v':
292                         verbose++;
293                         break;
294                 default:
295                         usage(cmd_subvol_delete_usage);
296                 }
297         }
298
299         if (check_argc_min(argc - optind, 1))
300                 usage(cmd_subvol_delete_usage);
301
302         if (verbose > 0) {
303                 printf("Transaction commit: %s\n",
304                         !commit_mode ? "none (default)" :
305                         commit_mode == COMMIT_AFTER ? "at the end" : "after each");
306         }
307
308         cnt = optind;
309
310 again:
311         path = argv[cnt];
312
313         res = test_issubvolume(path);
314         if (res < 0) {
315                 error("cannot access subvolume %s: %s", path, strerror(-res));
316                 ret = 1;
317                 goto out;
318         }
319         if (!res) {
320                 error("not a subvolume: %s", path);
321                 ret = 1;
322                 goto out;
323         }
324
325         cpath = realpath(path, NULL);
326         if (!cpath) {
327                 ret = errno;
328                 error("cannot find real path for '%s': %s",
329                         path, strerror(errno));
330                 goto out;
331         }
332         dupdname = strdup(cpath);
333         dname = dirname(dupdname);
334         dupvname = strdup(cpath);
335         vname = basename(dupvname);
336         free(cpath);
337
338         fd = btrfs_open_dir(dname, &dirstream, 1);
339         if (fd < 0) {
340                 ret = 1;
341                 goto out;
342         }
343
344         printf("Delete subvolume (%s): '%s/%s'\n",
345                 commit_mode == COMMIT_EACH || (commit_mode == COMMIT_AFTER && cnt + 1 == argc)
346                 ? "commit" : "no-commit", dname, vname);
347         memset(&args, 0, sizeof(args));
348         strncpy_null(args.name, vname);
349         res = ioctl(fd, BTRFS_IOC_SNAP_DESTROY, &args);
350         if(res < 0 ){
351                 error("cannot delete '%s/%s': %s", dname, vname,
352                         strerror(errno));
353                 ret = 1;
354                 goto out;
355         }
356
357         if (commit_mode == COMMIT_EACH) {
358                 res = wait_for_commit(fd);
359                 if (res < 0) {
360                         error("unable to wait for commit after '%s': %s",
361                                 path, strerror(errno));
362                         ret = 1;
363                 }
364         } else if (commit_mode == COMMIT_AFTER) {
365                 res = get_fsid(dname, fsid, 0);
366                 if (res < 0) {
367                         error("unable to get fsid for '%s': %s",
368                                 path, strerror(-res));
369                         error(
370                         "delete suceeded but commit may not be done in the end");
371                         ret = 1;
372                         goto out;
373                 }
374
375                 if (add_seen_fsid(fsid, seen_fsid_hash, fd, dirstream) == 0) {
376                         if (verbose > 0) {
377                                 uuid_unparse(fsid, uuidbuf);
378                                 printf("  new fs is found for '%s', fsid: %s\n",
379                                                 path, uuidbuf);
380                         }
381                         /*
382                          * This is the first time a subvolume on this
383                          * filesystem is deleted, keep fd in order to issue
384                          * SYNC ioctl in the end
385                          */
386                         goto keep_fd;
387                 }
388         }
389
390 out:
391         close_file_or_dir(fd, dirstream);
392 keep_fd:
393         fd = -1;
394         dirstream = NULL;
395         free(dupdname);
396         free(dupvname);
397         dupdname = NULL;
398         dupvname = NULL;
399         cnt++;
400         if (cnt < argc)
401                 goto again;
402
403         if (commit_mode == COMMIT_AFTER) {
404                 int slot;
405
406                 /*
407                  * Traverse seen_fsid_hash and issue SYNC ioctl on each
408                  * filesystem
409                  */
410                 for (slot = 0; slot < SEEN_FSID_HASH_SIZE; slot++) {
411                         struct seen_fsid *seen = seen_fsid_hash[slot];
412
413                         while (seen) {
414                                 res = wait_for_commit(seen->fd);
415                                 if (res < 0) {
416                                         uuid_unparse(seen->fsid, uuidbuf);
417                                         error(
418                         "unable to do final sync after deletion: %s, fsid: %s",
419                                                 strerror(errno), uuidbuf);
420                                         ret = 1;
421                                 } else if (verbose > 0) {
422                                         uuid_unparse(seen->fsid, uuidbuf);
423                                         printf("final sync is done for fsid: %s\n",
424                                                 uuidbuf);
425                                 }
426                                 seen = seen->next;
427                         }
428                 }
429                 /* fd will also be closed in free_seen_fsid */
430                 free_seen_fsid(seen_fsid_hash);
431         }
432
433         return ret;
434 }
435
436 /*
437  * Naming of options:
438  * - uppercase for filters and sort options
439  * - lowercase for enabling specific items in the output
440  */
441 static const char * const cmd_subvol_list_usage[] = {
442         "btrfs subvolume list [options] <path>",
443         "List subvolumes and snapshots in the filesystem.",
444         "",
445         "Path filtering:",
446         "-o           print only subvolumes below specified path",
447         "-a           print all the subvolumes in the filesystem and",
448         "             distinguish absolute and relative path with respect",
449         "             to the given <path>",
450         "",
451         "Field selection:",
452         "-p           print parent ID",
453         "-c           print the ogeneration of the subvolume",
454         "-g           print the generation of the subvolume",
455         "-u           print the uuid of subvolumes (and snapshots)",
456         "-q           print the parent uuid of the snapshots",
457         "-R           print the uuid of the received snapshots",
458         "",
459         "Type filtering:",
460         "-s           list only snapshots",
461         "-r           list readonly subvolumes (including snapshots)",
462         "-d           list deleted subvolumes that are not yet cleaned",
463         "",
464         "Other:",
465         "-t           print the result as a table",
466         "",
467         "Sorting:",
468         "-G [+|-]value",
469         "             filter the subvolumes by generation",
470         "             (+value: >= value; -value: <= value; value: = value)",
471         "-C [+|-]value",
472         "             filter the subvolumes by ogeneration",
473         "             (+value: >= value; -value: <= value; value: = value)",
474         "--sort=gen,ogen,rootid,path",
475         "             list the subvolume in order of gen, ogen, rootid or path",
476         "             you also can add '+' or '-' in front of each items.",
477         "             (+:ascending, -:descending, ascending default)",
478         NULL,
479 };
480
481 static int cmd_subvol_list(int argc, char **argv)
482 {
483         struct btrfs_list_filter_set *filter_set;
484         struct btrfs_list_comparer_set *comparer_set;
485         u64 flags = 0;
486         int fd = -1;
487         u64 top_id;
488         int ret = -1, uerr = 0;
489         char *subvol;
490         int is_list_all = 0;
491         int is_only_in_path = 0;
492         DIR *dirstream = NULL;
493         enum btrfs_list_layout layout = BTRFS_LIST_LAYOUT_DEFAULT;
494
495         filter_set = btrfs_list_alloc_filter_set();
496         comparer_set = btrfs_list_alloc_comparer_set();
497
498         while(1) {
499                 int c;
500                 static const struct option long_options[] = {
501                         {"sort", required_argument, NULL, 'S'},
502                         {NULL, 0, NULL, 0}
503                 };
504
505                 c = getopt_long(argc, argv,
506                                     "acdgopqsurRG:C:t", long_options, NULL);
507                 if (c < 0)
508                         break;
509
510                 switch(c) {
511                 case 'p':
512                         btrfs_list_setup_print_column(BTRFS_LIST_PARENT);
513                         break;
514                 case 'a':
515                         is_list_all = 1;
516                         break;
517                 case 'c':
518                         btrfs_list_setup_print_column(BTRFS_LIST_OGENERATION);
519                         break;
520                 case 'd':
521                         btrfs_list_setup_filter(&filter_set,
522                                                 BTRFS_LIST_FILTER_DELETED,
523                                                 0);
524                         break;
525                 case 'g':
526                         btrfs_list_setup_print_column(BTRFS_LIST_GENERATION);
527                         break;
528                 case 'o':
529                         is_only_in_path = 1;
530                         break;
531                 case 't':
532                         layout = BTRFS_LIST_LAYOUT_TABLE;
533                         break;
534                 case 's':
535                         btrfs_list_setup_filter(&filter_set,
536                                                 BTRFS_LIST_FILTER_SNAPSHOT_ONLY,
537                                                 0);
538                         btrfs_list_setup_print_column(BTRFS_LIST_OGENERATION);
539                         btrfs_list_setup_print_column(BTRFS_LIST_OTIME);
540                         break;
541                 case 'u':
542                         btrfs_list_setup_print_column(BTRFS_LIST_UUID);
543                         break;
544                 case 'q':
545                         btrfs_list_setup_print_column(BTRFS_LIST_PUUID);
546                         break;
547                 case 'R':
548                         btrfs_list_setup_print_column(BTRFS_LIST_RUUID);
549                         break;
550                 case 'r':
551                         flags |= BTRFS_ROOT_SUBVOL_RDONLY;
552                         break;
553                 case 'G':
554                         btrfs_list_setup_print_column(BTRFS_LIST_GENERATION);
555                         ret = btrfs_list_parse_filter_string(optarg,
556                                                         &filter_set,
557                                                         BTRFS_LIST_FILTER_GEN);
558                         if (ret) {
559                                 uerr = 1;
560                                 goto out;
561                         }
562                         break;
563
564                 case 'C':
565                         btrfs_list_setup_print_column(BTRFS_LIST_OGENERATION);
566                         ret = btrfs_list_parse_filter_string(optarg,
567                                                         &filter_set,
568                                                         BTRFS_LIST_FILTER_CGEN);
569                         if (ret) {
570                                 uerr = 1;
571                                 goto out;
572                         }
573                         break;
574                 case 'S':
575                         ret = btrfs_list_parse_sort_string(optarg,
576                                                            &comparer_set);
577                         if (ret) {
578                                 uerr = 1;
579                                 goto out;
580                         }
581                         break;
582
583                 default:
584                         uerr = 1;
585                         goto out;
586                 }
587         }
588
589         if (check_argc_exact(argc - optind, 1)) {
590                 uerr = 1;
591                 goto out;
592         }
593
594         subvol = argv[optind];
595         fd = btrfs_open_dir(subvol, &dirstream, 1);
596         if (fd < 0) {
597                 ret = -1;
598                 error("can't access '%s'", subvol);
599                 goto out;
600         }
601
602         if (flags)
603                 btrfs_list_setup_filter(&filter_set, BTRFS_LIST_FILTER_FLAGS,
604                                         flags);
605
606         ret = btrfs_list_get_path_rootid(fd, &top_id);
607         if (ret)
608                 goto out;
609
610         if (is_list_all)
611                 btrfs_list_setup_filter(&filter_set,
612                                         BTRFS_LIST_FILTER_FULL_PATH,
613                                         top_id);
614         else if (is_only_in_path)
615                 btrfs_list_setup_filter(&filter_set,
616                                         BTRFS_LIST_FILTER_TOPID_EQUAL,
617                                         top_id);
618
619         /* by default we shall print the following columns*/
620         btrfs_list_setup_print_column(BTRFS_LIST_OBJECTID);
621         btrfs_list_setup_print_column(BTRFS_LIST_GENERATION);
622         btrfs_list_setup_print_column(BTRFS_LIST_TOP_LEVEL);
623         btrfs_list_setup_print_column(BTRFS_LIST_PATH);
624
625         ret = btrfs_list_subvols_print(fd, filter_set, comparer_set,
626                         layout, !is_list_all && !is_only_in_path, NULL);
627
628 out:
629         close_file_or_dir(fd, dirstream);
630         if (filter_set)
631                 free(filter_set);
632         if (comparer_set)
633                 free(comparer_set);
634         if (uerr)
635                 usage(cmd_subvol_list_usage);
636         return !!ret;
637 }
638
639 static const char * const cmd_subvol_snapshot_usage[] = {
640         "btrfs subvolume snapshot [-r] [-i <qgroupid>] <source> <dest>|[<dest>/]<name>",
641         "Create a snapshot of the subvolume",
642         "Create a writable/readonly snapshot of the subvolume <source> with",
643         "the name <name> in the <dest> directory.  If only <dest> is given,",
644         "the subvolume will be named the basename of <source>.",
645         "",
646         "-r             create a readonly snapshot",
647         "-i <qgroupid>  add the newly created snapshot to a qgroup. This",
648         "               option can be given multiple times.",
649         NULL
650 };
651
652 static int cmd_subvol_snapshot(int argc, char **argv)
653 {
654         char    *subvol, *dst;
655         int     res, retval;
656         int     fd = -1, fddst = -1;
657         int     len, readonly = 0;
658         char    *dupname = NULL;
659         char    *dupdir = NULL;
660         char    *newname;
661         char    *dstdir;
662         struct btrfs_ioctl_vol_args_v2  args;
663         struct btrfs_qgroup_inherit *inherit = NULL;
664         DIR *dirstream1 = NULL, *dirstream2 = NULL;
665
666         memset(&args, 0, sizeof(args));
667         while (1) {
668                 int c = getopt(argc, argv, "c:i:r");
669                 if (c < 0)
670                         break;
671
672                 switch (c) {
673                 case 'c':
674                         res = qgroup_inherit_add_copy(&inherit, optarg, 0);
675                         if (res) {
676                                 retval = res;
677                                 goto out;
678                         }
679                         break;
680                 case 'i':
681                         res = qgroup_inherit_add_group(&inherit, optarg);
682                         if (res) {
683                                 retval = res;
684                                 goto out;
685                         }
686                         break;
687                 case 'r':
688                         readonly = 1;
689                         break;
690                 case 'x':
691                         res = qgroup_inherit_add_copy(&inherit, optarg, 1);
692                         if (res) {
693                                 retval = res;
694                                 goto out;
695                         }
696                         break;
697                 default:
698                         usage(cmd_subvol_snapshot_usage);
699                 }
700         }
701
702         if (check_argc_exact(argc - optind, 2))
703                 usage(cmd_subvol_snapshot_usage);
704
705         subvol = argv[optind];
706         dst = argv[optind + 1];
707
708         retval = 1;     /* failure */
709         res = test_issubvolume(subvol);
710         if (res < 0) {
711                 error("cannot access subvolume %s: %s", subvol, strerror(-res));
712                 goto out;
713         }
714         if (!res) {
715                 error("not a subvolume: %s", subvol);
716                 goto out;
717         }
718
719         res = test_isdir(dst);
720         if (res < 0 && res != -ENOENT) {
721                 error("cannot access %s: %s", dst, strerror(-res));
722                 goto out;
723         }
724         if (res == 0) {
725                 error("'%s' exists and it is not a directory", dst);
726                 goto out;
727         }
728
729         if (res > 0) {
730                 dupname = strdup(subvol);
731                 newname = basename(dupname);
732                 dstdir = dst;
733         } else {
734                 dupname = strdup(dst);
735                 newname = basename(dupname);
736                 dupdir = strdup(dst);
737                 dstdir = dirname(dupdir);
738         }
739
740         if (!test_issubvolname(newname)) {
741                 error("invalid snapshot name '%s'", newname);
742                 goto out;
743         }
744
745         len = strlen(newname);
746         if (len == 0 || len >= BTRFS_VOL_NAME_MAX) {
747                 error("snapshot name too long '%s'", newname);
748                 goto out;
749         }
750
751         fddst = btrfs_open_dir(dstdir, &dirstream1, 1);
752         if (fddst < 0)
753                 goto out;
754
755         fd = btrfs_open_dir(subvol, &dirstream2, 1);
756         if (fd < 0)
757                 goto out;
758
759         if (readonly) {
760                 args.flags |= BTRFS_SUBVOL_RDONLY;
761                 printf("Create a readonly snapshot of '%s' in '%s/%s'\n",
762                        subvol, dstdir, newname);
763         } else {
764                 printf("Create a snapshot of '%s' in '%s/%s'\n",
765                        subvol, dstdir, newname);
766         }
767
768         args.fd = fd;
769         if (inherit) {
770                 args.flags |= BTRFS_SUBVOL_QGROUP_INHERIT;
771                 args.size = qgroup_inherit_size(inherit);
772                 args.qgroup_inherit = inherit;
773         }
774         strncpy_null(args.name, newname);
775
776         res = ioctl(fddst, BTRFS_IOC_SNAP_CREATE_V2, &args);
777
778         if (res < 0) {
779                 error("cannot snapshot '%s': %s", subvol, strerror(errno));
780                 goto out;
781         }
782
783         retval = 0;     /* success */
784
785 out:
786         close_file_or_dir(fddst, dirstream1);
787         close_file_or_dir(fd, dirstream2);
788         free(inherit);
789         free(dupname);
790         free(dupdir);
791
792         return retval;
793 }
794
795 static const char * const cmd_subvol_get_default_usage[] = {
796         "btrfs subvolume get-default <path>",
797         "Get the default subvolume of a filesystem",
798         NULL
799 };
800
801 static int cmd_subvol_get_default(int argc, char **argv)
802 {
803         int fd = -1;
804         int ret;
805         char *subvol;
806         struct btrfs_list_filter_set *filter_set;
807         u64 default_id;
808         DIR *dirstream = NULL;
809
810         clean_args_no_options(argc, argv, cmd_subvol_get_default_usage);
811
812         if (check_argc_exact(argc - optind, 1))
813                 usage(cmd_subvol_get_default_usage);
814
815         subvol = argv[1];
816         fd = btrfs_open_dir(subvol, &dirstream, 1);
817         if (fd < 0)
818                 return 1;
819
820         ret = btrfs_list_get_default_subvolume(fd, &default_id);
821         if (ret) {
822                 error("failed to look up default subvolume: %s",
823                         strerror(errno));
824                 goto out;
825         }
826
827         ret = 1;
828         if (default_id == 0) {
829                 error("'default' dir item not found");
830                 goto out;
831         }
832
833         /* no need to resolve roots if FS_TREE is default */
834         if (default_id == BTRFS_FS_TREE_OBJECTID) {
835                 printf("ID 5 (FS_TREE)\n");
836                 ret = 0;
837                 goto out;
838         }
839
840         filter_set = btrfs_list_alloc_filter_set();
841         btrfs_list_setup_filter(&filter_set, BTRFS_LIST_FILTER_ROOTID,
842                                 default_id);
843
844         /* by default we shall print the following columns*/
845         btrfs_list_setup_print_column(BTRFS_LIST_OBJECTID);
846         btrfs_list_setup_print_column(BTRFS_LIST_GENERATION);
847         btrfs_list_setup_print_column(BTRFS_LIST_TOP_LEVEL);
848         btrfs_list_setup_print_column(BTRFS_LIST_PATH);
849
850         ret = btrfs_list_subvols_print(fd, filter_set, NULL,
851                 BTRFS_LIST_LAYOUT_DEFAULT, 1, NULL);
852
853         if (filter_set)
854                 free(filter_set);
855 out:
856         close_file_or_dir(fd, dirstream);
857         return !!ret;
858 }
859
860 static const char * const cmd_subvol_set_default_usage[] = {
861         "btrfs subvolume set-default <subvolume>\n"
862         "btrfs subvolume set-default <subvolid> <path>",
863         "Set the default subvolume of the filesystem mounted as default.",
864         "The subvolume can be specified by its path,",
865         "or the pair of subvolume id and path to the filesystem.",
866         NULL
867 };
868
869 static int cmd_subvol_set_default(int argc, char **argv)
870 {
871         int     ret=0, fd, e;
872         u64     objectid;
873         char    *path;
874         char    *subvolid;
875         DIR     *dirstream = NULL;
876
877         clean_args_no_options(argc, argv, cmd_subvol_set_default_usage);
878
879         if (check_argc_min(argc - optind, 1) ||
880                         check_argc_max(argc - optind, 2))
881                 usage(cmd_subvol_set_default_usage);
882
883         if (argc - optind == 1) {
884                 /* path to the subvolume is specified */
885                 path = argv[optind];
886
887                 ret = test_issubvolume(path);
888                 if (ret < 0) {
889                         error("stat error: %s", strerror(-ret));
890                         return 1;
891                 } else if (!ret) {
892                         error("'%s' is not a subvolume", path);
893                         return 1;
894                 }
895
896                 fd = btrfs_open_dir(path, &dirstream, 1);
897                 if (fd < 0)
898                         return 1;
899
900                 ret = lookup_path_rootid(fd, &objectid);
901                 if (ret) {
902                         error("unable to get subvol id: %s", strerror(-ret));
903                         close_file_or_dir(fd, dirstream);
904                         return 1;
905                 }
906         } else {
907                 /* subvol id and path to the filesystem are specified */
908                 subvolid = argv[optind];
909                 path = argv[optind + 1];
910                 objectid = arg_strtou64(subvolid);
911
912                 fd = btrfs_open_dir(path, &dirstream, 1);
913                 if (fd < 0)
914                         return 1;
915         }
916
917         ret = ioctl(fd, BTRFS_IOC_DEFAULT_SUBVOL, &objectid);
918         e = errno;
919         close_file_or_dir(fd, dirstream);
920         if (ret < 0) {
921                 error("unable to set a new default subvolume: %s",
922                         strerror(e));
923                 return 1;
924         }
925         return 0;
926 }
927
928 static const char * const cmd_subvol_find_new_usage[] = {
929         "btrfs subvolume find-new <path> <lastgen>",
930         "List the recently modified files in a filesystem",
931         NULL
932 };
933
934 static int cmd_subvol_find_new(int argc, char **argv)
935 {
936         int fd;
937         int ret;
938         char *subvol;
939         u64 last_gen;
940         DIR *dirstream = NULL;
941
942         clean_args_no_options(argc, argv, cmd_subvol_find_new_usage);
943
944         if (check_argc_exact(argc - optind, 2))
945                 usage(cmd_subvol_find_new_usage);
946
947         subvol = argv[optind];
948         last_gen = arg_strtou64(argv[optind + 1]);
949
950         ret = test_issubvolume(subvol);
951         if (ret < 0) {
952                 error("cannot access subvolume %s: %s", subvol, strerror(-ret));
953                 return 1;
954         }
955         if (!ret) {
956                 error("not a subvolume: %s", subvol);
957                 return 1;
958         }
959
960         fd = btrfs_open_dir(subvol, &dirstream, 1);
961         if (fd < 0)
962                 return 1;
963
964         ret = ioctl(fd, BTRFS_IOC_SYNC);
965         if (ret < 0) {
966                 error("sync ioctl failed on '%s': %s",
967                         subvol, strerror(errno));
968                 close_file_or_dir(fd, dirstream);
969                 return 1;
970         }
971
972         ret = btrfs_list_find_updated_files(fd, 0, last_gen);
973         close_file_or_dir(fd, dirstream);
974         return !!ret;
975 }
976
977 static const char * const cmd_subvol_show_usage[] = {
978         "btrfs subvolume show [options] <subvol-path>|<mnt>",
979         "Show more information about the subvolume",
980         "-r|--rootid   rootid of the subvolume",
981         "-u|--uuid     uuid of the subvolume",
982         "",
983         "If no option is specified, <subvol-path> will be shown, otherwise",
984         "the rootid or uuid are resolved relative to the <mnt> path.",
985         NULL
986 };
987
988 static int cmd_subvol_show(int argc, char **argv)
989 {
990         struct root_info get_ri;
991         struct btrfs_list_filter_set *filter_set = NULL;
992         char tstr[256];
993         char uuidparse[BTRFS_UUID_UNPARSED_SIZE];
994         char *fullpath = NULL;
995         char raw_prefix[] = "\t\t\t\t";
996         int fd = -1;
997         int ret = 1;
998         DIR *dirstream1 = NULL;
999         int by_rootid = 0;
1000         int by_uuid = 0;
1001         u64 rootid_arg;
1002         u8 uuid_arg[BTRFS_UUID_SIZE];
1003
1004         while (1) {
1005                 int c;
1006                 static const struct option long_options[] = {
1007                         { "rootid", required_argument, NULL, 'r'},
1008                         { "uuid", required_argument, NULL, 'u'},
1009                         { NULL, 0, NULL, 0 }
1010                 };
1011
1012                 c = getopt_long(argc, argv, "r:u:", long_options, NULL);
1013                 if (c < 0)
1014                         break;
1015
1016                 switch (c) {
1017                 case 'r':
1018                         rootid_arg = arg_strtou64(optarg);
1019                         by_rootid = 1;
1020                         break;
1021                 case 'u':
1022                         uuid_parse(optarg, uuid_arg);
1023                         by_uuid = 1;
1024                         break;
1025                 default:
1026                         usage(cmd_subvol_show_usage);
1027                 }
1028         }
1029
1030         if (check_argc_exact(argc - optind, 1))
1031                 usage(cmd_subvol_show_usage);
1032
1033         if (by_rootid && by_uuid) {
1034                 error(
1035                 "options --rootid and --uuid cannot be used at the same time");
1036                 usage(cmd_subvol_show_usage);
1037         }
1038
1039         memset(&get_ri, 0, sizeof(get_ri));
1040         fullpath = realpath(argv[optind], NULL);
1041         if (!fullpath) {
1042                 error("cannot find real path for '%s': %s",
1043                         argv[optind], strerror(errno));
1044                 goto out;
1045         }
1046
1047         if (by_rootid) {
1048                 ret = get_subvol_info_by_rootid(fullpath, &get_ri, rootid_arg);
1049         } else if (by_uuid) {
1050                 ret = get_subvol_info_by_uuid(fullpath, &get_ri, uuid_arg);
1051         } else {
1052                 ret = get_subvol_info(fullpath, &get_ri);
1053         }
1054
1055         if (ret) {
1056                 if (ret < 0) {
1057                         error("Failed to get subvol info %s: %s",
1058                                         fullpath, strerror(-ret));
1059                 } else {
1060                         error("Failed to get subvol info %s: %d",
1061                                         fullpath, ret);
1062                 }
1063                 return ret;
1064         }
1065
1066         /* print the info */
1067         printf("%s\n", get_ri.full_path);
1068         printf("\tName: \t\t\t%s\n", get_ri.name);
1069
1070         if (uuid_is_null(get_ri.uuid))
1071                 strcpy(uuidparse, "-");
1072         else
1073                 uuid_unparse(get_ri.uuid, uuidparse);
1074         printf("\tUUID: \t\t\t%s\n", uuidparse);
1075
1076         if (uuid_is_null(get_ri.puuid))
1077                 strcpy(uuidparse, "-");
1078         else
1079                 uuid_unparse(get_ri.puuid, uuidparse);
1080         printf("\tParent UUID: \t\t%s\n", uuidparse);
1081
1082         if (uuid_is_null(get_ri.ruuid))
1083                 strcpy(uuidparse, "-");
1084         else
1085                 uuid_unparse(get_ri.ruuid, uuidparse);
1086         printf("\tReceived UUID: \t\t%s\n", uuidparse);
1087
1088         if (get_ri.otime) {
1089                 struct tm tm;
1090
1091                 localtime_r(&get_ri.otime, &tm);
1092                 strftime(tstr, 256, "%Y-%m-%d %X %z", &tm);
1093         } else
1094                 strcpy(tstr, "-");
1095         printf("\tCreation time: \t\t%s\n", tstr);
1096
1097         printf("\tSubvolume ID: \t\t%llu\n", get_ri.root_id);
1098         printf("\tGeneration: \t\t%llu\n", get_ri.gen);
1099         printf("\tGen at creation: \t%llu\n", get_ri.ogen);
1100         printf("\tParent ID: \t\t%llu\n", get_ri.ref_tree);
1101         printf("\tTop level ID: \t\t%llu\n", get_ri.top_id);
1102
1103         if (get_ri.flags & BTRFS_ROOT_SUBVOL_RDONLY)
1104                 printf("\tFlags: \t\t\treadonly\n");
1105         else
1106                 printf("\tFlags: \t\t\t-\n");
1107
1108         /* print the snapshots of the given subvol if any*/
1109         printf("\tSnapshot(s):\n");
1110         filter_set = btrfs_list_alloc_filter_set();
1111         btrfs_list_setup_filter(&filter_set, BTRFS_LIST_FILTER_BY_PARENT,
1112                                 (u64)(unsigned long)get_ri.uuid);
1113         btrfs_list_setup_print_column(BTRFS_LIST_PATH);
1114
1115         fd = open_file_or_dir(fullpath, &dirstream1);
1116         if (fd < 0) {
1117                 fprintf(stderr, "ERROR: can't access '%s'\n", fullpath);
1118                 goto out;
1119         }
1120         btrfs_list_subvols_print(fd, filter_set, NULL, BTRFS_LIST_LAYOUT_RAW,
1121                         1, raw_prefix);
1122
1123 out:
1124         /* clean up */
1125         free(get_ri.path);
1126         free(get_ri.name);
1127         free(get_ri.full_path);
1128         free(filter_set);
1129
1130         close_file_or_dir(fd, dirstream1);
1131         free(fullpath);
1132         return !!ret;
1133 }
1134
1135 static const char * const cmd_subvol_sync_usage[] = {
1136         "btrfs subvolume sync <path> [<subvol-id>...]",
1137         "Wait until given subvolume(s) are completely removed from the filesystem.",
1138         "Wait until given subvolume(s) are completely removed from the filesystem",
1139         "after deletion.",
1140         "If no subvolume id is given, wait until all current deletion requests",
1141         "are completed, but do not wait for subvolumes deleted meanwhile.",
1142         "The status of subvolume ids is checked periodically.",
1143         "",
1144         "-s <N>       sleep N seconds between checks (default: 1)",
1145         NULL
1146 };
1147
1148 #if 0
1149 /*
1150  * If we're looking for any dead subvolume, take a shortcut and look
1151  * for any ORPHAN_ITEMs in the tree root
1152  */
1153 static int fs_has_dead_subvolumes(int fd)
1154 {
1155         int ret;
1156         struct btrfs_ioctl_search_args args;
1157         struct btrfs_ioctl_search_key *sk = &args.key;
1158         struct btrfs_ioctl_search_header sh;
1159         u64 min_subvolid = 0;
1160
1161 again:
1162         sk->tree_id = BTRFS_ROOT_TREE_OBJECTID;
1163         sk->min_objectid = BTRFS_ORPHAN_OBJECTID;
1164         sk->max_objectid = BTRFS_ORPHAN_OBJECTID;
1165         sk->min_type = BTRFS_ORPHAN_ITEM_KEY;
1166         sk->max_type = BTRFS_ORPHAN_ITEM_KEY;
1167         sk->min_offset = min_subvolid;
1168         sk->max_offset = (u64)-1;
1169         sk->min_transid = 0;
1170         sk->max_transid = (u64)-1;
1171         sk->nr_items = 1;
1172
1173         ret = ioctl(fd, BTRFS_IOC_TREE_SEARCH, &args);
1174         if (ret < 0)
1175                 return -errno;
1176
1177         if (!sk->nr_items)
1178                 return 0;
1179
1180         memcpy(&sh, args.buf, sizeof(sh));
1181         min_subvolid = sh.offset;
1182
1183         /*
1184          * Verify that the root item is really there and we haven't hit
1185          * a stale orphan
1186          */
1187         sk->tree_id = BTRFS_ROOT_TREE_OBJECTID;
1188         sk->min_objectid = min_subvolid;
1189         sk->max_objectid = min_subvolid;
1190         sk->min_type = BTRFS_ROOT_ITEM_KEY;
1191         sk->max_type = BTRFS_ROOT_ITEM_KEY;
1192         sk->min_offset = 0;
1193         sk->max_offset = (u64)-1;
1194         sk->min_transid = 0;
1195         sk->max_transid = (u64)-1;
1196         sk->nr_items = 1;
1197
1198         ret = ioctl(fd, BTRFS_IOC_TREE_SEARCH, &args);
1199         if (ret < 0)
1200                 return -errno;
1201
1202         /*
1203          * Stale orphan, try the next one
1204          */
1205         if (!sk->nr_items) {
1206                 min_subvolid++;
1207                 goto again;
1208         }
1209
1210         return 1;
1211 }
1212 #endif
1213
1214 #define SUBVOL_ID_BATCH         1024
1215
1216 /*
1217  * Enumerate all dead subvolumes that exist in the filesystem.
1218  * Fill @ids and reallocate to bigger size if needed.
1219  */
1220 static int enumerate_dead_subvols(int fd, u64 **ids)
1221 {
1222         int ret;
1223         struct btrfs_ioctl_search_args args;
1224         struct btrfs_ioctl_search_key *sk = &args.key;
1225         int idx = 0;
1226         int count = 0;
1227
1228         memset(&args, 0, sizeof(args));
1229
1230         sk->tree_id = BTRFS_ROOT_TREE_OBJECTID;
1231         sk->min_objectid = BTRFS_ORPHAN_OBJECTID;
1232         sk->max_objectid = BTRFS_ORPHAN_OBJECTID;
1233         sk->min_type = BTRFS_ORPHAN_ITEM_KEY;
1234         sk->max_type = BTRFS_ORPHAN_ITEM_KEY;
1235         sk->min_offset = 0;
1236         sk->max_offset = (u64)-1;
1237         sk->min_transid = 0;
1238         sk->max_transid = (u64)-1;
1239         sk->nr_items = 4096;
1240
1241         *ids = NULL;
1242         while (1) {
1243                 struct btrfs_ioctl_search_header *sh;
1244                 unsigned long off;
1245                 int i;
1246
1247                 ret = ioctl(fd, BTRFS_IOC_TREE_SEARCH, &args);
1248                 if (ret < 0)
1249                         return -errno;
1250
1251                 if (!sk->nr_items)
1252                         return idx;
1253
1254                 off = 0;
1255                 for (i = 0; i < sk->nr_items; i++) {
1256                         sh = (struct btrfs_ioctl_search_header*)(args.buf + off);
1257                         off += sizeof(*sh);
1258
1259                         if (btrfs_search_header_type(sh)
1260                             == BTRFS_ORPHAN_ITEM_KEY) {
1261                                 if (idx >= count) {
1262                                         u64 *newids;
1263
1264                                         count += SUBVOL_ID_BATCH;
1265                                         newids = (u64*)realloc(*ids,
1266                                                         count * sizeof(u64));
1267                                         if (!newids)
1268                                                 return -ENOMEM;
1269                                         *ids = newids;
1270                                 }
1271                                 (*ids)[idx] = btrfs_search_header_offset(sh);
1272                                 idx++;
1273                         }
1274                         off += btrfs_search_header_len(sh);
1275
1276                         sk->min_objectid = btrfs_search_header_objectid(sh);
1277                         sk->min_type = btrfs_search_header_type(sh);
1278                         sk->min_offset = btrfs_search_header_offset(sh);
1279                 }
1280                 if (sk->min_offset < (u64)-1)
1281                         sk->min_offset++;
1282                 else
1283                         break;
1284                 if (sk->min_type != BTRFS_ORPHAN_ITEM_KEY)
1285                         break;
1286                 if (sk->min_objectid != BTRFS_ORPHAN_OBJECTID)
1287                         break;
1288         }
1289
1290         return idx;
1291 }
1292
1293 static int cmd_subvol_sync(int argc, char **argv)
1294 {
1295         int fd = -1;
1296         int i;
1297         int ret = 1;
1298         DIR *dirstream = NULL;
1299         u64 *ids = NULL;
1300         int id_count;
1301         int sleep_interval = 1;
1302
1303         while (1) {
1304                 int c = getopt(argc, argv, "s:");
1305
1306                 if (c < 0)
1307                         break;
1308
1309                 switch (c) {
1310                 case 's':
1311                         sleep_interval = atoi(optarg);
1312                         if (sleep_interval < 1) {
1313                                 error("invalid sleep interval %s", optarg);
1314                                 ret = 1;
1315                                 goto out;
1316                         }
1317                         break;
1318                 default:
1319                         usage(cmd_subvol_sync_usage);
1320                 }
1321         }
1322
1323         if (check_argc_min(argc - optind, 1))
1324                 usage(cmd_subvol_sync_usage);
1325
1326         fd = btrfs_open_dir(argv[optind], &dirstream, 1);
1327         if (fd < 0) {
1328                 ret = 1;
1329                 goto out;
1330         }
1331         optind++;
1332
1333         id_count = argc - optind;
1334         if (!id_count) {
1335                 id_count = enumerate_dead_subvols(fd, &ids);
1336                 if (id_count < 0) {
1337                         error("can't enumerate dead subvolumes: %s",
1338                                         strerror(-id_count));
1339                         ret = 1;
1340                         goto out;
1341                 }
1342                 if (id_count == 0) {
1343                         ret = 0;
1344                         goto out;
1345                 }
1346         } else {
1347                 ids = (u64*)malloc(id_count * sizeof(u64));
1348                 if (!ids) {
1349                         error("not enough memory");
1350                         ret = 1;
1351                         goto out;
1352                 }
1353
1354                 for (i = 0; i < id_count; i++) {
1355                         u64 id;
1356                         const char *arg;
1357
1358                         arg = argv[optind + i];
1359                         errno = 0;
1360                         id = strtoull(arg, NULL, 10);
1361                         if (errno < 0) {
1362                                 error("unrecognized subvolume id %s", arg);
1363                                 ret = 1;
1364                                 goto out;
1365                         }
1366                         if (id < BTRFS_FIRST_FREE_OBJECTID
1367                                         || id > BTRFS_LAST_FREE_OBJECTID) {
1368                                 error("subvolume id %s out of range", arg);
1369                                 ret = 1;
1370                                 goto out;
1371                         }
1372                         ids[i] = id;
1373                 }
1374         }
1375
1376         ret = wait_for_subvolume_cleaning(fd, id_count, ids, sleep_interval);
1377
1378 out:
1379         free(ids);
1380         close_file_or_dir(fd, dirstream);
1381
1382         return !!ret;
1383 }
1384
1385 static const char subvolume_cmd_group_info[] =
1386 "manage subvolumes: create, delete, list, etc";
1387
1388 const struct cmd_group subvolume_cmd_group = {
1389         subvolume_cmd_group_usage, subvolume_cmd_group_info, {
1390                 { "create", cmd_subvol_create, cmd_subvol_create_usage, NULL, 0 },
1391                 { "delete", cmd_subvol_delete, cmd_subvol_delete_usage, NULL, 0 },
1392                 { "list", cmd_subvol_list, cmd_subvol_list_usage, NULL, 0 },
1393                 { "snapshot", cmd_subvol_snapshot, cmd_subvol_snapshot_usage,
1394                         NULL, 0 },
1395                 { "get-default", cmd_subvol_get_default,
1396                         cmd_subvol_get_default_usage, NULL, 0 },
1397                 { "set-default", cmd_subvol_set_default,
1398                         cmd_subvol_set_default_usage, NULL, 0 },
1399                 { "find-new", cmd_subvol_find_new, cmd_subvol_find_new_usage,
1400                         NULL, 0 },
1401                 { "show", cmd_subvol_show, cmd_subvol_show_usage, NULL, 0 },
1402                 { "sync", cmd_subvol_sync, cmd_subvol_sync_usage, NULL, 0 },
1403                 NULL_CMD_STRUCT
1404         }
1405 };
1406
1407 int cmd_subvolume(int argc, char **argv)
1408 {
1409         return handle_command_group(&subvolume_cmd_group, argc, argv);
1410 }