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"
43 #include "btrfslabel.h"
46 #define BLKGETSIZE64 0
47 #define BTRFS_IOC_SNAP_CREATE_V2 0
48 #define BTRFS_VOL_NAME_MAX 255
49 struct btrfs_ioctl_vol_args
{ char name
[BTRFS_VOL_NAME_MAX
]; };
50 static inline int ioctl(int fd
, int define
, void *arg
) { return 0; }
54 * test if path is a subvolume:
55 * this function return
56 * 0-> path exists but it is not a subvolume
57 * 1-> path exists and it is a subvolume
58 * -1 -> path is unaccessible
60 static int test_issubvolume(char *path
)
66 res
= stat(path
, &st
);
70 return (st
.st_ino
== 256) && S_ISDIR(st
.st_mode
);
75 * test if path is a directory
76 * this function return
77 * 0-> path exists but it is not a directory
78 * 1-> path exists and it is a directory
79 * -1 -> path is unaccessible
81 static int test_isdir(char *path
)
86 res
= stat(path
, &st
);
90 return S_ISDIR(st
.st_mode
);
94 int open_file_or_dir(const char *fname
)
101 ret
= stat(fname
, &st
);
105 if (S_ISDIR(st
.st_mode
)) {
106 dirstream
= opendir(fname
);
110 fd
= dirfd(dirstream
);
112 fd
= open(fname
, O_RDWR
);
120 static u64
parse_size(char *s
)
126 if (!isdigit(s
[len
- 1])) {
127 c
= tolower(s
[len
- 1]);
138 fprintf(stderr
, "Unknown size descriptor %c\n", c
);
143 return atoll(s
) * mult
;
146 static int parse_compress_type(char *s
)
148 if (strcmp(optarg
, "zlib") == 0)
149 return BTRFS_COMPRESS_ZLIB
;
150 else if (strcmp(optarg
, "lzo") == 0)
151 return BTRFS_COMPRESS_LZO
;
153 fprintf(stderr
, "Unknown compress type %s\n", s
);
158 int do_defrag(int ac
, char **av
)
170 struct btrfs_ioctl_defrag_range_args range
;
172 int compress_type
= BTRFS_COMPRESS_NONE
;
176 int c
= getopt(ac
, av
, "vc::fs:l:t:");
181 compress_type
= BTRFS_COMPRESS_ZLIB
;
183 compress_type
= parse_compress_type(optarg
);
194 start
= parse_size(optarg
);
198 len
= parse_size(optarg
);
202 thresh
= parse_size(optarg
);
206 fprintf(stderr
, "Invalid arguments for defragment\n");
211 if (ac
- optind
== 0) {
212 fprintf(stderr
, "Invalid arguments for defragment\n");
217 memset(&range
, 0, sizeof(range
));
220 range
.extent_thresh
= thresh
;
222 range
.flags
|= BTRFS_DEFRAG_RANGE_COMPRESS
;
223 range
.compress_type
= compress_type
;
226 range
.flags
|= BTRFS_DEFRAG_RANGE_START_IO
;
228 for (i
= optind
; i
< ac
; i
++) {
230 printf("%s\n", av
[i
]);
231 fd
= open_file_or_dir(av
[i
]);
233 fprintf(stderr
, "failed to open %s\n", av
[i
]);
239 ret
= ioctl(fd
, BTRFS_IOC_DEFRAG
, NULL
);
242 ret
= ioctl(fd
, BTRFS_IOC_DEFRAG_RANGE
, &range
);
243 if (ret
&& errno
== ENOTTY
) {
244 fprintf(stderr
, "ERROR: defrag range ioctl not "
245 "supported in this kernel, please try "
246 "without any options.\n");
253 fprintf(stderr
, "ERROR: defrag failed on %s - %s\n",
260 printf("%s\n", BTRFS_BUILD_VERSION
);
262 fprintf(stderr
, "total %d failures\n", errors
);
270 int do_find_newer(int argc
, char **argv
)
278 last_gen
= atoll(argv
[2]);
280 ret
= test_issubvolume(subvol
);
282 fprintf(stderr
, "ERROR: error accessing '%s'\n", subvol
);
286 fprintf(stderr
, "ERROR: '%s' is not a subvolume\n", subvol
);
290 fd
= open_file_or_dir(subvol
);
292 fprintf(stderr
, "ERROR: can't access '%s'\n", subvol
);
295 ret
= find_updated_files(fd
, 0, last_gen
);
301 int do_subvol_list(int argc
, char **argv
)
305 int print_parent
= 0;
310 int c
= getopt(argc
, argv
, "p");
320 if (argc
- optind
!= 1) {
321 fprintf(stderr
, "ERROR: invalid arguments for subvolume list\n");
325 subvol
= argv
[optind
];
327 ret
= test_issubvolume(subvol
);
329 fprintf(stderr
, "ERROR: error accessing '%s'\n", subvol
);
333 fprintf(stderr
, "ERROR: '%s' is not a subvolume\n", subvol
);
337 fd
= open_file_or_dir(subvol
);
339 fprintf(stderr
, "ERROR: can't access '%s'\n", subvol
);
342 ret
= list_subvols(fd
, print_parent
, 0);
348 int do_clone(int argc
, char **argv
)
351 int res
, fd
, fddst
, len
, e
, optind
= 0, readonly
= 0;
354 struct btrfs_ioctl_vol_args_v2 args
;
356 memset(&args
, 0, sizeof(args
));
359 int c
= getopt(argc
, argv
, "r");
370 "Invalid arguments for subvolume snapshot\n");
375 if (argc
- optind
!= 3) {
376 fprintf(stderr
, "Invalid arguments for subvolume snapshot\n");
381 subvol
= argv
[optind
+1];
382 dst
= argv
[optind
+2];
384 res
= test_issubvolume(subvol
);
386 fprintf(stderr
, "ERROR: error accessing '%s'\n", subvol
);
390 fprintf(stderr
, "ERROR: '%s' is not a subvolume\n", subvol
);
394 res
= test_isdir(dst
);
396 fprintf(stderr
, "ERROR: '%s' exists and it is not a directory\n", dst
);
401 newname
= strdup(subvol
);
402 newname
= basename(newname
);
405 newname
= strdup(dst
);
406 newname
= basename(newname
);
407 dstdir
= strdup(dst
);
408 dstdir
= dirname(dstdir
);
411 if( !strcmp(newname
,".") || !strcmp(newname
,"..") ||
412 strchr(newname
, '/') ){
413 fprintf(stderr
, "ERROR: incorrect snapshot name ('%s')\n",
418 len
= strlen(newname
);
419 if (len
== 0 || len
>= BTRFS_VOL_NAME_MAX
) {
420 fprintf(stderr
, "ERROR: snapshot name too long ('%s)\n",
425 fddst
= open_file_or_dir(dstdir
);
427 fprintf(stderr
, "ERROR: can't access to '%s'\n", dstdir
);
431 fd
= open_file_or_dir(subvol
);
434 fprintf(stderr
, "ERROR: can't access to '%s'\n", dstdir
);
439 args
.flags
|= BTRFS_SUBVOL_RDONLY
;
440 printf("Create a readonly snapshot of '%s' in '%s/%s'\n",
441 subvol
, dstdir
, newname
);
443 printf("Create a snapshot of '%s' in '%s/%s'\n",
444 subvol
, dstdir
, newname
);
448 strncpy(args
.name
, newname
, BTRFS_SUBVOL_NAME_MAX
);
449 res
= ioctl(fddst
, BTRFS_IOC_SNAP_CREATE_V2
, &args
);
456 fprintf( stderr
, "ERROR: cannot snapshot '%s' - %s\n",
457 subvol
, strerror(e
));
465 int do_delete_subvolume(int argc
, char **argv
)
468 struct btrfs_ioctl_vol_args args
;
469 char *dname
, *vname
, *cpath
;
470 char *path
= argv
[1];
472 res
= test_issubvolume(path
);
474 fprintf(stderr
, "ERROR: error accessing '%s'\n", path
);
478 fprintf(stderr
, "ERROR: '%s' is not a subvolume\n", path
);
482 cpath
= realpath(path
, 0);
483 dname
= strdup(cpath
);
484 dname
= dirname(dname
);
485 vname
= strdup(cpath
);
486 vname
= basename(vname
);
489 if( !strcmp(vname
,".") || !strcmp(vname
,"..") ||
490 strchr(vname
, '/') ){
491 fprintf(stderr
, "ERROR: incorrect subvolume name ('%s')\n",
497 if (len
== 0 || len
>= BTRFS_VOL_NAME_MAX
) {
498 fprintf(stderr
, "ERROR: snapshot name too long ('%s)\n",
503 fd
= open_file_or_dir(dname
);
506 fprintf(stderr
, "ERROR: can't access to '%s'\n", dname
);
510 printf("Delete subvolume '%s/%s'\n", dname
, vname
);
511 strncpy(args
.name
, vname
, BTRFS_PATH_NAME_MAX
);
512 res
= ioctl(fd
, BTRFS_IOC_SNAP_DESTROY
, &args
);
518 fprintf( stderr
, "ERROR: cannot delete '%s/%s' - %s\n",
519 dname
, vname
, strerror(e
));
527 int do_create_subvol(int argc
, char **argv
)
529 int res
, fddst
, len
, e
;
532 struct btrfs_ioctl_vol_args args
;
535 res
= test_isdir(dst
);
537 fprintf(stderr
, "ERROR: '%s' exists\n", dst
);
541 newname
= strdup(dst
);
542 newname
= basename(newname
);
543 dstdir
= strdup(dst
);
544 dstdir
= dirname(dstdir
);
546 if( !strcmp(newname
,".") || !strcmp(newname
,"..") ||
547 strchr(newname
, '/') ){
548 fprintf(stderr
, "ERROR: uncorrect subvolume name ('%s')\n",
553 len
= strlen(newname
);
554 if (len
== 0 || len
>= BTRFS_VOL_NAME_MAX
) {
555 fprintf(stderr
, "ERROR: subvolume name too long ('%s)\n",
560 fddst
= open_file_or_dir(dstdir
);
562 fprintf(stderr
, "ERROR: can't access to '%s'\n", dstdir
);
566 printf("Create subvolume '%s/%s'\n", dstdir
, newname
);
567 strncpy(args
.name
, newname
, BTRFS_PATH_NAME_MAX
);
568 res
= ioctl(fddst
, BTRFS_IOC_SUBVOL_CREATE
, &args
);
574 fprintf( stderr
, "ERROR: cannot create subvolume - %s\n",
583 int do_fssync(int argc
, char **argv
)
586 char *path
= argv
[1];
588 fd
= open_file_or_dir(path
);
590 fprintf(stderr
, "ERROR: can't access to '%s'\n", path
);
594 printf("FSSync '%s'\n", path
);
595 res
= ioctl(fd
, BTRFS_IOC_SYNC
);
599 fprintf(stderr
, "ERROR: unable to fs-syncing '%s' - %s\n",
607 int do_scan(int argc
, char **argv
)
613 if( argc
>= 2 && !strcmp(argv
[1],"--all-devices")){
616 fprintf(stderr
, "ERROR: too may arguments\n");
628 printf("Scanning for Btrfs filesystems\n");
630 ret
= btrfs_scan_block_devices(1);
632 ret
= btrfs_scan_one_dir("/dev", 1);
634 fprintf(stderr
, "ERROR: error %d while scanning\n", ret
);
640 fd
= open("/dev/btrfs-control", O_RDWR
);
642 perror("failed to open /dev/btrfs-control");
646 for( i
= devstart
; i
< argc
; i
++ ){
647 struct btrfs_ioctl_vol_args args
;
650 printf("Scanning for Btrfs filesystems in '%s'\n", argv
[i
]);
652 strncpy(args
.name
, argv
[i
], BTRFS_PATH_NAME_MAX
);
654 * FIXME: which are the error code returned by this ioctl ?
655 * it seems that is impossible to understand if there no is
656 * a btrfs filesystem from an I/O error !!!
658 ret
= ioctl(fd
, BTRFS_IOC_SCAN_DEV
, &args
);
663 fprintf(stderr
, "ERROR: unable to scan the device '%s' - %s\n",
664 argv
[i
], strerror(e
));
674 int do_resize(int argc
, char **argv
)
677 struct btrfs_ioctl_vol_args args
;
679 char *amount
=argv
[1], *path
=argv
[2];
681 fd
= open_file_or_dir(path
);
683 fprintf(stderr
, "ERROR: can't access to '%s'\n", path
);
686 len
= strlen(amount
);
687 if (len
== 0 || len
>= BTRFS_VOL_NAME_MAX
) {
688 fprintf(stderr
, "ERROR: size value too long ('%s)\n",
693 printf("Resize '%s' of '%s'\n", path
, amount
);
694 strncpy(args
.name
, amount
, BTRFS_PATH_NAME_MAX
);
695 res
= ioctl(fd
, BTRFS_IOC_RESIZE
, &args
);
699 fprintf(stderr
, "ERROR: unable to resize '%s' - %s\n",
706 static int uuid_search(struct btrfs_fs_devices
*fs_devices
, char *search
)
708 struct list_head
*cur
;
709 struct btrfs_device
*device
;
711 list_for_each(cur
, &fs_devices
->devices
) {
712 device
= list_entry(cur
, struct btrfs_device
, dev_list
);
713 if ((device
->label
&& strcmp(device
->label
, search
) == 0) ||
714 strcmp(device
->name
, search
) == 0)
720 static void print_one_uuid(struct btrfs_fs_devices
*fs_devices
)
723 struct list_head
*cur
;
724 struct btrfs_device
*device
;
725 char *super_bytes_used
;
729 uuid_unparse(fs_devices
->fsid
, uuidbuf
);
730 device
= list_entry(fs_devices
->devices
.next
, struct btrfs_device
,
732 if (device
->label
&& device
->label
[0])
733 printf("Label: '%s' ", device
->label
);
735 printf("Label: none ");
737 super_bytes_used
= pretty_sizes(device
->super_bytes_used
);
739 total
= device
->total_devs
;
740 printf(" uuid: %s\n\tTotal devices %llu FS bytes used %s\n", uuidbuf
,
741 (unsigned long long)total
, super_bytes_used
);
743 free(super_bytes_used
);
745 list_for_each(cur
, &fs_devices
->devices
) {
748 device
= list_entry(cur
, struct btrfs_device
, dev_list
);
749 total_bytes
= pretty_sizes(device
->total_bytes
);
750 bytes_used
= pretty_sizes(device
->bytes_used
);
751 printf("\tdevid %4llu size %s used %s path %s\n",
752 (unsigned long long)device
->devid
,
753 total_bytes
, bytes_used
, device
->name
);
758 if (devs_found
< total
) {
759 printf("\t*** Some devices missing\n");
764 int do_show_filesystem(int argc
, char **argv
)
766 struct list_head
*all_uuids
;
767 struct btrfs_fs_devices
*fs_devices
;
768 struct list_head
*cur_uuid
;
774 if( argc
>= 2 && !strcmp(argv
[1],"--all-devices")){
779 if( argc
> searchstart
+1 ){
780 fprintf(stderr
, "ERROR: too many arguments\n");
785 ret
= btrfs_scan_block_devices(0);
787 ret
= btrfs_scan_one_dir("/dev", 0);
790 fprintf(stderr
, "ERROR: error %d while scanning\n", ret
);
794 if(searchstart
< argc
)
795 search
= argv
[searchstart
];
797 all_uuids
= btrfs_scanned_uuids();
798 list_for_each(cur_uuid
, all_uuids
) {
799 fs_devices
= list_entry(cur_uuid
, struct btrfs_fs_devices
,
801 if (search
&& uuid_search(fs_devices
, search
) == 0)
803 print_one_uuid(fs_devices
);
805 printf("%s\n", BTRFS_BUILD_VERSION
);
809 int do_add_volume(int nargs
, char **args
)
812 char *mntpnt
= args
[nargs
-1];
813 int i
, fdmnt
, ret
=0, e
;
816 fdmnt
= open_file_or_dir(mntpnt
);
818 fprintf(stderr
, "ERROR: can't access to '%s'\n", mntpnt
);
822 for (i
= 1; i
< (nargs
-1); i
++ ){
823 struct btrfs_ioctl_vol_args ioctl_args
;
825 u64 dev_block_count
= 0;
829 res
= check_mounted(args
[i
]);
831 fprintf(stderr
, "error checking %s mount status\n",
837 fprintf(stderr
, "%s is mounted\n", args
[i
]);
842 devfd
= open(args
[i
], O_RDWR
);
844 fprintf(stderr
, "ERROR: Unable to open device '%s'\n", args
[i
]);
849 res
= fstat(devfd
, &st
);
851 fprintf(stderr
, "ERROR: Unable to stat '%s'\n", args
[i
]);
856 if (!S_ISBLK(st
.st_mode
)) {
857 fprintf(stderr
, "ERROR: '%s' is not a block device\n", args
[i
]);
863 res
= btrfs_prepare_device(devfd
, args
[i
], 1, &dev_block_count
, &mixed
);
865 fprintf(stderr
, "ERROR: Unable to init '%s'\n", args
[i
]);
872 strncpy(ioctl_args
.name
, args
[i
], BTRFS_PATH_NAME_MAX
);
873 res
= ioctl(fdmnt
, BTRFS_IOC_ADD_DEV
, &ioctl_args
);
876 fprintf(stderr
, "ERROR: error adding the device '%s' - %s\n",
877 args
[i
], strerror(e
));
891 int do_balance(int argc
, char **argv
)
895 struct btrfs_ioctl_vol_args args
;
896 char *path
= argv
[1];
898 fdmnt
= open_file_or_dir(path
);
900 fprintf(stderr
, "ERROR: can't access to '%s'\n", path
);
904 memset(&args
, 0, sizeof(args
));
905 ret
= ioctl(fdmnt
, BTRFS_IOC_BALANCE
, &args
);
909 fprintf(stderr
, "ERROR: error during balancing '%s' - %s\n",
916 int do_remove_volume(int nargs
, char **args
)
919 char *mntpnt
= args
[nargs
-1];
920 int i
, fdmnt
, ret
=0, e
;
922 fdmnt
= open_file_or_dir(mntpnt
);
924 fprintf(stderr
, "ERROR: can't access to '%s'\n", mntpnt
);
928 for(i
=1 ; i
< (nargs
-1) ; i
++ ){
929 struct btrfs_ioctl_vol_args arg
;
932 strncpy(arg
.name
, args
[i
], BTRFS_PATH_NAME_MAX
);
933 res
= ioctl(fdmnt
, BTRFS_IOC_RM_DEV
, &arg
);
936 fprintf(stderr
, "ERROR: error removing the device '%s' - %s\n",
937 args
[i
], strerror(e
));
949 int do_set_default_subvol(int nargs
, char **argv
)
953 char *path
= argv
[2];
954 char *subvolid
= argv
[1];
956 fd
= open_file_or_dir(path
);
958 fprintf(stderr
, "ERROR: can't access to '%s'\n", path
);
962 objectid
= (unsigned long long)strtoll(subvolid
, NULL
, 0);
963 if (errno
== ERANGE
) {
964 fprintf(stderr
, "ERROR: invalid tree id (%s)\n",subvolid
);
967 ret
= ioctl(fd
, BTRFS_IOC_DEFAULT_SUBVOL
, &objectid
);
971 fprintf(stderr
, "ERROR: unable to set a new default subvolume - %s\n",
978 int do_change_label(int nargs
, char **argv
)
980 /* check the number of argument */
982 fprintf(stderr
, "ERROR: '%s' requires maximum 2 args\n",
985 }else if (nargs
== 2){
986 return get_label(argv
[1]);
987 } else { /* nargs == 0 */
988 return set_label(argv
[1], argv
[2]);
993 int do_get_default_subvol(int nargs
, char **argv
)
1001 ret
= test_issubvolume(subvol
);
1003 fprintf(stderr
, "ERROR: error accessing '%s'\n", subvol
);
1007 fprintf(stderr
, "ERROR: '%s' is not a subvolume\n", subvol
);
1011 fd
= open_file_or_dir(subvol
);
1013 fprintf(stderr
, "ERROR: can't access '%s'\n", subvol
);
1016 ret
= list_subvols(fd
, 0, 1);
1022 int do_df_filesystem(int nargs
, char **argv
)
1024 struct btrfs_ioctl_space_args
*sargs
;
1029 char *path
= argv
[1];
1031 fd
= open_file_or_dir(path
);
1033 fprintf(stderr
, "ERROR: can't access to '%s'\n", path
);
1037 sargs
= malloc(sizeof(struct btrfs_ioctl_space_args
));
1041 sargs
->space_slots
= 0;
1042 sargs
->total_spaces
= 0;
1044 ret
= ioctl(fd
, BTRFS_IOC_SPACE_INFO
, sargs
);
1047 fprintf(stderr
, "ERROR: couldn't get space info on '%s' - %s\n",
1052 if (!sargs
->total_spaces
)
1055 count
= sargs
->total_spaces
;
1057 sargs
= realloc(sargs
, sizeof(struct btrfs_ioctl_space_args
) +
1058 (count
* sizeof(struct btrfs_ioctl_space_info
)));
1062 sargs
->space_slots
= count
;
1063 sargs
->total_spaces
= 0;
1065 ret
= ioctl(fd
, BTRFS_IOC_SPACE_INFO
, sargs
);
1068 fprintf(stderr
, "ERROR: couldn't get space info on '%s' - %s\n",
1075 for (i
= 0; i
< sargs
->total_spaces
; i
++) {
1076 char description
[80];
1080 u64 flags
= sargs
->spaces
[i
].flags
;
1082 memset(description
, 0, 80);
1084 if (flags
& BTRFS_BLOCK_GROUP_DATA
) {
1085 if (flags
& BTRFS_BLOCK_GROUP_METADATA
) {
1086 snprintf(description
, 14, "%s",
1090 snprintf(description
, 5, "%s", "Data");
1093 } else if (flags
& BTRFS_BLOCK_GROUP_SYSTEM
) {
1094 snprintf(description
, 7, "%s", "System");
1096 } else if (flags
& BTRFS_BLOCK_GROUP_METADATA
) {
1097 snprintf(description
, 9, "%s", "Metadata");
1101 if (flags
& BTRFS_BLOCK_GROUP_RAID0
) {
1102 snprintf(description
+written
, 8, "%s", ", RAID0");
1104 } else if (flags
& BTRFS_BLOCK_GROUP_RAID1
) {
1105 snprintf(description
+written
, 8, "%s", ", RAID1");
1107 } else if (flags
& BTRFS_BLOCK_GROUP_DUP
) {
1108 snprintf(description
+written
, 6, "%s", ", DUP");
1110 } else if (flags
& BTRFS_BLOCK_GROUP_RAID10
) {
1111 snprintf(description
+written
, 9, "%s", ", RAID10");
1115 total_bytes
= pretty_sizes(sargs
->spaces
[i
].total_bytes
);
1116 used_bytes
= pretty_sizes(sargs
->spaces
[i
].used_bytes
);
1117 printf("%s: total=%s, used=%s\n", description
, total_bytes
,