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.
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.
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.
21 #include <sys/ioctl.h>
22 #include <sys/types.h>
29 #include <uuid/uuid.h>
34 #include "kerncompat.h"
36 #include "transaction.h"
42 #include "btrfs_cmds.h"
45 #define BLKGETSIZE64 0
46 #define BTRFS_IOC_SNAP_CREATE 0
47 #define BTRFS_VOL_NAME_MAX 255
48 struct btrfs_ioctl_vol_args
{ char name
[BTRFS_VOL_NAME_MAX
]; };
49 static inline int ioctl(int fd
, int define
, void *arg
) { return 0; }
53 * test if path is a subvolume:
54 * this function return
55 * 0-> path exists but it is not a subvolume
56 * 1-> path exists and it is a subvolume
57 * -1 -> path is unaccessible
59 static int test_issubvolume(char *path
)
65 res
= stat(path
, &st
);
69 return (st
.st_ino
== 256) && S_ISDIR(st
.st_mode
);
74 * test if path is a directory
75 * this function return
76 * 0-> path exists but it is not a directory
77 * 1-> path exists and it is a directory
78 * -1 -> path is unaccessible
80 static int test_isdir(char *path
)
85 res
= stat(path
, &st
);
89 return S_ISDIR(st
.st_mode
);
93 static int open_file_or_dir(const char *fname
)
100 ret
= stat(fname
, &st
);
104 if (S_ISDIR(st
.st_mode
)) {
105 dirstream
= opendir(fname
);
109 fd
= dirfd(dirstream
);
111 fd
= open(fname
, O_RDWR
);
119 static u64
parse_size(char *s
)
125 if (!isdigit(s
[len
- 1])) {
126 c
= tolower(s
[len
- 1]);
137 fprintf(stderr
, "Unknown size descriptor %c\n", c
);
142 return atoll(s
) * mult
;
145 int do_defrag(int ac
, char **av
)
158 struct btrfs_ioctl_defrag_range_args range
;
162 int c
= getopt(ac
, av
, "vcfs:l:t:");
178 start
= parse_size(optarg
);
182 len
= parse_size(optarg
);
186 thresh
= parse_size(optarg
);
190 fprintf(stderr
, "Invalid arguments for defragment\n");
195 if (ac
- optind
== 0) {
196 fprintf(stderr
, "Invalid arguments for defragment\n");
201 memset(&range
, 0, sizeof(range
));
204 range
.extent_thresh
= thresh
;
206 range
.flags
|= BTRFS_DEFRAG_RANGE_COMPRESS
;
208 range
.flags
|= BTRFS_DEFRAG_RANGE_START_IO
;
210 for (i
= optind
; i
< ac
; i
++) {
212 printf("%s\n", av
[i
]);
213 fd
= open_file_or_dir(av
[i
]);
215 fprintf(stderr
, "failed to open %s\n", av
[i
]);
221 ret
= ioctl(fd
, BTRFS_IOC_DEFRAG
, NULL
);
223 ret
= ioctl(fd
, BTRFS_IOC_DEFRAG_RANGE
, &range
);
224 if (ret
&& errno
== ENOTTY
) {
225 fprintf(stderr
, "defrag range ioctl not "
226 "supported in this kernel, please try "
227 "without any options.\n");
233 fprintf(stderr
, "ioctl failed on %s ret %d errno %d\n",
240 printf("%s\n", BTRFS_BUILD_VERSION
);
242 fprintf(stderr
, "total %d failures\n", errors
);
250 int do_find_newer(int argc
, char **argv
)
258 last_gen
= atoll(argv
[2]);
260 ret
= test_issubvolume(subvol
);
262 fprintf(stderr
, "ERROR: error accessing '%s'\n", subvol
);
266 fprintf(stderr
, "ERROR: '%s' is not a subvolume\n", subvol
);
270 fd
= open_file_or_dir(subvol
);
272 fprintf(stderr
, "ERROR: can't access '%s'\n", subvol
);
275 ret
= find_updated_files(fd
, 0, last_gen
);
281 int do_subvol_list(int argc
, char **argv
)
289 ret
= test_issubvolume(subvol
);
291 fprintf(stderr
, "ERROR: error accessing '%s'\n", subvol
);
295 fprintf(stderr
, "ERROR: '%s' is not a subvolume\n", subvol
);
299 fd
= open_file_or_dir(subvol
);
301 fprintf(stderr
, "ERROR: can't access '%s'\n", subvol
);
304 ret
= list_subvols(fd
);
310 int do_clone(int argc
, char **argv
)
313 int res
, fd
, fddst
, len
;
319 struct btrfs_ioctl_vol_args args
;
321 res
= test_issubvolume(subvol
);
323 fprintf(stderr
, "ERROR: error accessing '%s'\n", subvol
);
327 fprintf(stderr
, "ERROR: '%s' is not a subvolume\n", subvol
);
331 res
= test_isdir(dst
);
333 fprintf(stderr
, "ERROR: '%s' exists and it is not a directory\n", dst
);
338 newname
= strdup(subvol
);
339 newname
= basename(newname
);
342 newname
= strdup(dst
);
343 newname
= basename(newname
);
344 dstdir
= strdup(dst
);
345 dstdir
= dirname(dstdir
);
348 if( !strcmp(newname
,".") || !strcmp(newname
,"..") ||
349 strchr(newname
, '/') ){
350 fprintf(stderr
, "ERROR: incorrect snapshot name ('%s')\n",
355 len
= strlen(newname
);
356 if (len
== 0 || len
>= BTRFS_VOL_NAME_MAX
) {
357 fprintf(stderr
, "ERROR: snapshot name too long ('%s)\n",
362 fddst
= open_file_or_dir(dstdir
);
364 fprintf(stderr
, "ERROR: can't access to '%s'\n", dstdir
);
368 fd
= open_file_or_dir(subvol
);
371 fprintf(stderr
, "ERROR: can't access to '%s'\n", dstdir
);
375 printf("Create a snapshot of '%s' in '%s/%s'\n",
376 subvol
, dstdir
, newname
);
378 strcpy(args
.name
, newname
);
379 res
= ioctl(fddst
, BTRFS_IOC_SNAP_CREATE
, &args
);
385 fprintf( stderr
, "ERROR: cannot snapshot '%s'\n",subvol
);
393 int do_delete_subvolume(int argc
, char **argv
)
396 struct btrfs_ioctl_vol_args args
;
397 char *dname
, *vname
, *cpath
;
398 char *path
= argv
[1];
400 res
= test_issubvolume(path
);
402 fprintf(stderr
, "ERROR: error accessing '%s'\n", path
);
406 fprintf(stderr
, "ERROR: '%s' is not a subvolume\n", path
);
410 cpath
= realpath(path
, 0);
411 dname
= strdup(cpath
);
412 dname
= dirname(dname
);
413 vname
= strdup(cpath
);
414 vname
= basename(vname
);
417 if( !strcmp(vname
,".") || !strcmp(vname
,"..") ||
418 strchr(vname
, '/') ){
419 fprintf(stderr
, "ERROR: incorrect subvolume name ('%s')\n",
425 if (len
== 0 || len
>= BTRFS_VOL_NAME_MAX
) {
426 fprintf(stderr
, "ERROR: snapshot name too long ('%s)\n",
431 fd
= open_file_or_dir(dname
);
434 fprintf(stderr
, "ERROR: can't access to '%s'\n", dname
);
438 printf("Delete subvolume '%s/%s'\n", dname
, vname
);
439 strcpy(args
.name
, vname
);
440 res
= ioctl(fd
, BTRFS_IOC_SNAP_DESTROY
, &args
);
445 fprintf( stderr
, "ERROR: cannot delete '%s/%s'\n",dname
, vname
);
453 int do_create_subvol(int argc
, char **argv
)
458 struct btrfs_ioctl_vol_args args
;
461 res
= test_isdir(dst
);
463 fprintf(stderr
, "ERROR: '%s' exists\n", dst
);
467 newname
= strdup(dst
);
468 newname
= basename(newname
);
469 dstdir
= strdup(dst
);
470 dstdir
= dirname(dstdir
);
472 if( !strcmp(newname
,".") || !strcmp(newname
,"..") ||
473 strchr(newname
, '/') ){
474 fprintf(stderr
, "ERROR: uncorrect subvolume name ('%s')\n",
479 len
= strlen(newname
);
480 if (len
== 0 || len
>= BTRFS_VOL_NAME_MAX
) {
481 fprintf(stderr
, "ERROR: subvolume name too long ('%s)\n",
486 fddst
= open_file_or_dir(dstdir
);
488 fprintf(stderr
, "ERROR: can't access to '%s'\n", dstdir
);
492 printf("Create subvolume '%s/%s'\n", dstdir
, newname
);
493 strcpy(args
.name
, newname
);
494 res
= ioctl(fddst
, BTRFS_IOC_SUBVOL_CREATE
, &args
);
499 fprintf( stderr
, "ERROR: cannot create subvolume\n");
507 int do_fssync(int argc
, char **argv
)
510 char *path
= argv
[1];
512 fd
= open_file_or_dir(path
);
514 fprintf(stderr
, "ERROR: can't access to '%s'\n", path
);
518 printf("FSSync '%s'\n", path
);
519 res
= ioctl(fd
, BTRFS_IOC_SYNC
);
522 fprintf(stderr
, "ERROR: unable to fs-syncing '%s'\n", path
);
529 int do_scan(int argc
, char **argv
)
535 printf("Scanning for Btrfs filesystems\n");
536 ret
= btrfs_scan_one_dir("/dev", 1);
538 fprintf(stderr
, "ERROR: error %d while scanning\n", ret
);
544 fd
= open("/dev/btrfs-control", O_RDWR
);
546 perror("failed to open /dev/btrfs-control");
550 for( i
= 1 ; i
< argc
; i
++ ){
551 struct btrfs_ioctl_vol_args args
;
554 printf("Scanning for Btrfs filesystems in '%s'\n", argv
[i
]);
556 strcpy(args
.name
, argv
[i
]);
558 * FIXME: which are the error code returned by this ioctl ?
559 * it seems that is impossible to understand if there no is
560 * a btrfs filesystem from an I/O error !!!
562 ret
= ioctl(fd
, BTRFS_IOC_SCAN_DEV
, &args
);
566 fprintf(stderr
, "ERROR: unable to scan the device '%s'\n", argv
[i
]);
576 int do_resize(int argc
, char **argv
)
579 struct btrfs_ioctl_vol_args args
;
581 char *amount
=argv
[1], *path
=argv
[2];
583 fd
= open_file_or_dir(path
);
585 fprintf(stderr
, "ERROR: can't access to '%s'\n", path
);
588 len
= strlen(amount
);
589 if (len
== 0 || len
>= BTRFS_VOL_NAME_MAX
) {
590 fprintf(stderr
, "ERROR: size value too long ('%s)\n",
595 printf("Resize '%s' of '%s'\n", path
, amount
);
596 strcpy(args
.name
, amount
);
597 res
= ioctl(fd
, BTRFS_IOC_RESIZE
, &args
);
600 fprintf(stderr
, "ERROR: unable to resize '%s'\n", path
);
606 static int uuid_search(struct btrfs_fs_devices
*fs_devices
, char *search
)
608 struct list_head
*cur
;
609 struct btrfs_device
*device
;
611 list_for_each(cur
, &fs_devices
->devices
) {
612 device
= list_entry(cur
, struct btrfs_device
, dev_list
);
613 if ((device
->label
&& strcmp(device
->label
, search
) == 0) ||
614 strcmp(device
->name
, search
) == 0)
620 static void print_one_uuid(struct btrfs_fs_devices
*fs_devices
)
623 struct list_head
*cur
;
624 struct btrfs_device
*device
;
625 char *super_bytes_used
;
629 uuid_unparse(fs_devices
->fsid
, uuidbuf
);
630 device
= list_entry(fs_devices
->devices
.next
, struct btrfs_device
,
632 if (device
->label
&& device
->label
[0])
633 printf("Label: '%s' ", device
->label
);
635 printf("Label: none ");
637 super_bytes_used
= pretty_sizes(device
->super_bytes_used
);
639 total
= device
->total_devs
;
640 printf(" uuid: %s\n\tTotal devices %llu FS bytes used %s\n", uuidbuf
,
641 (unsigned long long)total
, super_bytes_used
);
643 free(super_bytes_used
);
645 list_for_each(cur
, &fs_devices
->devices
) {
648 device
= list_entry(cur
, struct btrfs_device
, dev_list
);
649 total_bytes
= pretty_sizes(device
->total_bytes
);
650 bytes_used
= pretty_sizes(device
->bytes_used
);
651 printf("\tdevid %4llu size %s used %s path %s\n",
652 (unsigned long long)device
->devid
,
653 total_bytes
, bytes_used
, device
->name
);
658 if (devs_found
< total
) {
659 printf("\t*** Some devices missing\n");
664 int do_show_filesystem(int argc
, char **argv
)
666 struct list_head
*all_uuids
;
667 struct btrfs_fs_devices
*fs_devices
;
668 struct list_head
*cur_uuid
;
669 char *search
= argv
[1];
672 ret
= btrfs_scan_one_dir("/dev", 0);
674 fprintf(stderr
, "ERROR: error %d while scanning\n", ret
);
678 all_uuids
= btrfs_scanned_uuids();
679 list_for_each(cur_uuid
, all_uuids
) {
680 fs_devices
= list_entry(cur_uuid
, struct btrfs_fs_devices
,
682 if (search
&& uuid_search(fs_devices
, search
) == 0)
684 print_one_uuid(fs_devices
);
686 printf("%s\n", BTRFS_BUILD_VERSION
);
690 int do_add_volume(int nargs
, char **args
)
693 char *mntpnt
= args
[nargs
-1];
697 fdmnt
= open_file_or_dir(mntpnt
);
699 fprintf(stderr
, "ERROR: can't access to '%s'\n", mntpnt
);
703 for(i
=1 ; i
< (nargs
-1) ; i
++ ){
704 struct btrfs_ioctl_vol_args ioctl_args
;
706 u64 dev_block_count
= 0;
709 devfd
= open(args
[i
], O_RDWR
);
711 fprintf(stderr
, "ERROR: Unable to open device '%s'\n", args
[i
]);
716 ret
= fstat(devfd
, &st
);
718 fprintf(stderr
, "ERROR: Unable to stat '%s'\n", args
[i
]);
723 if (!S_ISBLK(st
.st_mode
)) {
724 fprintf(stderr
, "ERROR: '%s' is not a block device\n", args
[i
]);
730 res
= btrfs_prepare_device(devfd
, args
[i
], 1, &dev_block_count
);
732 fprintf(stderr
, "ERROR: Unable to init '%s'\n", args
[i
]);
739 strcpy(ioctl_args
.name
, args
[i
]);
740 res
= ioctl(fdmnt
, BTRFS_IOC_ADD_DEV
, &ioctl_args
);
742 fprintf(stderr
, "ERROR: error adding the device '%s'\n", args
[i
]);
756 int do_balance(int argc
, char **argv
)
760 struct btrfs_ioctl_vol_args args
;
761 char *path
= argv
[1];
763 fdmnt
= open_file_or_dir(path
);
765 fprintf(stderr
, "ERROR: can't access to '%s'\n", path
);
769 memset(&args
, 0, sizeof(args
));
770 ret
= ioctl(fdmnt
, BTRFS_IOC_BALANCE
, &args
);
773 fprintf(stderr
, "ERROR: balancing '%s'\n", path
);
779 int do_remove_volume(int nargs
, char **args
)
782 char *mntpnt
= args
[nargs
-1];
785 fdmnt
= open_file_or_dir(mntpnt
);
787 fprintf(stderr
, "ERROR: can't access to '%s'\n", mntpnt
);
791 for(i
=1 ; i
< (nargs
-1) ; i
++ ){
792 struct btrfs_ioctl_vol_args arg
;
795 strcpy(arg
.name
, args
[i
]);
796 res
= ioctl(fdmnt
, BTRFS_IOC_RM_DEV
, &arg
);
798 fprintf(stderr
, "ERROR: error removing the device '%s'\n", args
[i
]);
810 int do_set_default_subvol(int nargs
, char **argv
)
814 char *path
= argv
[2];
815 char *subvolid
= argv
[1];
817 fd
= open_file_or_dir(path
);
819 fprintf(stderr
, "ERROR: can't access to '%s'\n", path
);
823 objectid
= (unsigned long long)strtoll(subvolid
, NULL
, 0);
824 if (errno
== ERANGE
) {
825 fprintf(stderr
, "ERROR: invalid tree id (%s)\n",subvolid
);
828 ret
= ioctl(fd
, BTRFS_IOC_DEFAULT_SUBVOL
, &objectid
);
831 fprintf(stderr
, "ERROR: unable to set a new default subvolume\n");
837 int do_df_filesystem(int nargs
, char **argv
)
839 struct btrfs_ioctl_space_args
*sargs
;
843 char *path
= argv
[1];
845 fd
= open_file_or_dir(path
);
847 fprintf(stderr
, "ERROR: can't access to '%s'\n", path
);
851 sargs
= malloc(sizeof(struct btrfs_ioctl_space_args
));
855 sargs
->space_slots
= 0;
856 sargs
->total_spaces
= 0;
858 ret
= ioctl(fd
, BTRFS_IOC_SPACE_INFO
, sargs
);
863 if (!sargs
->total_spaces
)
866 count
= sargs
->total_spaces
;
868 sargs
= realloc(sargs
, sizeof(struct btrfs_ioctl_space_args
) +
869 (count
* sizeof(struct btrfs_ioctl_space_info
)));
873 sargs
->space_slots
= count
;
874 sargs
->total_spaces
= 0;
876 ret
= ioctl(fd
, BTRFS_IOC_SPACE_INFO
, sargs
);
882 for (i
= 0; i
< sargs
->total_spaces
; i
++) {
883 char description
[80];
887 u64 flags
= sargs
->spaces
[i
].flags
;
889 memset(description
, 0, 80);
891 if (flags
& BTRFS_BLOCK_GROUP_DATA
) {
892 snprintf(description
, 5, "%s", "Data");
894 } else if (flags
& BTRFS_BLOCK_GROUP_SYSTEM
) {
895 snprintf(description
, 7, "%s", "System");
897 } else if (flags
& BTRFS_BLOCK_GROUP_METADATA
) {
898 snprintf(description
, 9, "%s", "Metadata");
902 if (flags
& BTRFS_BLOCK_GROUP_RAID0
) {
903 snprintf(description
+written
, 8, "%s", ", RAID0");
905 } else if (flags
& BTRFS_BLOCK_GROUP_RAID1
) {
906 snprintf(description
+written
, 8, "%s", ", RAID1");
908 } else if (flags
& BTRFS_BLOCK_GROUP_DUP
) {
909 snprintf(description
+written
, 6, "%s", ", DUP");
911 } else if (flags
& BTRFS_BLOCK_GROUP_RAID10
) {
912 snprintf(description
+written
, 9, "%s", ", RAID10");
916 total_bytes
= pretty_sizes(sargs
->spaces
[i
].total_bytes
);
917 used_bytes
= pretty_sizes(sargs
->spaces
[i
].used_bytes
);
918 printf("%s: total=%s, used=%s\n", description
, total_bytes
,