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