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>
23 #include <uuid/uuid.h>
26 #include "kerncompat.h"
35 #include "btrfslabel.h"
37 static const char * const filesystem_cmd_group_usage
[] = {
38 "btrfs filesystem [<group>] <command> [<args>]",
42 static const char * const cmd_df_usage
[] = {
43 "btrfs filesystem df <path>",
44 "Show space usage information for a mount point",
48 static int cmd_df(int argc
, char **argv
)
50 struct btrfs_ioctl_space_args
*sargs
;
57 if (check_argc_exact(argc
, 2))
62 fd
= open_file_or_dir(path
);
64 fprintf(stderr
, "ERROR: can't access to '%s'\n", path
);
68 sargs
= malloc(sizeof(struct btrfs_ioctl_space_args
));
72 sargs
->space_slots
= 0;
73 sargs
->total_spaces
= 0;
75 ret
= ioctl(fd
, BTRFS_IOC_SPACE_INFO
, sargs
);
78 fprintf(stderr
, "ERROR: couldn't get space info on '%s' - %s\n",
83 if (!sargs
->total_spaces
)
86 count
= sargs
->total_spaces
;
88 sargs
= realloc(sargs
, sizeof(struct btrfs_ioctl_space_args
) +
89 (count
* sizeof(struct btrfs_ioctl_space_info
)));
93 sargs
->space_slots
= count
;
94 sargs
->total_spaces
= 0;
96 ret
= ioctl(fd
, BTRFS_IOC_SPACE_INFO
, sargs
);
99 fprintf(stderr
, "ERROR: couldn't get space info on '%s' - %s\n",
106 for (i
= 0; i
< sargs
->total_spaces
; i
++) {
107 char description
[80];
111 u64 flags
= sargs
->spaces
[i
].flags
;
113 memset(description
, 0, 80);
115 if (flags
& BTRFS_BLOCK_GROUP_DATA
) {
116 if (flags
& BTRFS_BLOCK_GROUP_METADATA
) {
117 snprintf(description
, 14, "%s",
121 snprintf(description
, 5, "%s", "Data");
124 } else if (flags
& BTRFS_BLOCK_GROUP_SYSTEM
) {
125 snprintf(description
, 7, "%s", "System");
127 } else if (flags
& BTRFS_BLOCK_GROUP_METADATA
) {
128 snprintf(description
, 9, "%s", "Metadata");
132 if (flags
& BTRFS_BLOCK_GROUP_RAID0
) {
133 snprintf(description
+written
, 8, "%s", ", RAID0");
135 } else if (flags
& BTRFS_BLOCK_GROUP_RAID1
) {
136 snprintf(description
+written
, 8, "%s", ", RAID1");
138 } else if (flags
& BTRFS_BLOCK_GROUP_DUP
) {
139 snprintf(description
+written
, 6, "%s", ", DUP");
141 } else if (flags
& BTRFS_BLOCK_GROUP_RAID10
) {
142 snprintf(description
+written
, 9, "%s", ", RAID10");
146 total_bytes
= pretty_sizes(sargs
->spaces
[i
].total_bytes
);
147 used_bytes
= pretty_sizes(sargs
->spaces
[i
].used_bytes
);
148 printf("%s: total=%s, used=%s\n", description
, total_bytes
,
156 static int uuid_search(struct btrfs_fs_devices
*fs_devices
, char *search
)
159 struct list_head
*cur
;
160 struct btrfs_device
*device
;
161 int search_len
= strlen(search
);
163 search_len
= min(search_len
, 37);
164 uuid_unparse(fs_devices
->fsid
, uuidbuf
);
165 if (!strncmp(uuidbuf
, search
, search_len
))
168 list_for_each(cur
, &fs_devices
->devices
) {
169 device
= list_entry(cur
, struct btrfs_device
, dev_list
);
170 if ((device
->label
&& strcmp(device
->label
, search
) == 0) ||
171 strcmp(device
->name
, search
) == 0)
177 static void print_one_uuid(struct btrfs_fs_devices
*fs_devices
)
180 struct list_head
*cur
;
181 struct btrfs_device
*device
;
182 char *super_bytes_used
;
186 uuid_unparse(fs_devices
->fsid
, uuidbuf
);
187 device
= list_entry(fs_devices
->devices
.next
, struct btrfs_device
,
189 if (device
->label
&& device
->label
[0])
190 printf("Label: '%s' ", device
->label
);
192 printf("Label: none ");
194 super_bytes_used
= pretty_sizes(device
->super_bytes_used
);
196 total
= device
->total_devs
;
197 printf(" uuid: %s\n\tTotal devices %llu FS bytes used %s\n", uuidbuf
,
198 (unsigned long long)total
, super_bytes_used
);
200 free(super_bytes_used
);
202 list_for_each(cur
, &fs_devices
->devices
) {
205 device
= list_entry(cur
, struct btrfs_device
, dev_list
);
206 total_bytes
= pretty_sizes(device
->total_bytes
);
207 bytes_used
= pretty_sizes(device
->bytes_used
);
208 printf("\tdevid %4llu size %s used %s path %s\n",
209 (unsigned long long)device
->devid
,
210 total_bytes
, bytes_used
, device
->name
);
215 if (devs_found
< total
) {
216 printf("\t*** Some devices missing\n");
221 static const char * const cmd_show_usage
[] = {
222 "btrfs filesystem show [--all-devices] [<uuid>|<label>]",
223 "Show the structure of a filesystem",
224 "If no argument is given, structure of all present filesystems is shown.",
228 static int cmd_show(int argc
, char **argv
)
230 struct list_head
*all_uuids
;
231 struct btrfs_fs_devices
*fs_devices
;
232 struct list_head
*cur_uuid
;
238 if( argc
> 1 && !strcmp(argv
[1],"--all-devices")){
243 if (check_argc_max(argc
, searchstart
+ 1))
244 usage(cmd_show_usage
);
247 ret
= btrfs_scan_block_devices(0);
249 ret
= btrfs_scan_one_dir("/dev", 0);
252 fprintf(stderr
, "ERROR: error %d while scanning\n", ret
);
256 if(searchstart
< argc
)
257 search
= argv
[searchstart
];
259 all_uuids
= btrfs_scanned_uuids();
260 list_for_each(cur_uuid
, all_uuids
) {
261 fs_devices
= list_entry(cur_uuid
, struct btrfs_fs_devices
,
263 if (search
&& uuid_search(fs_devices
, search
) == 0)
265 print_one_uuid(fs_devices
);
267 printf("%s\n", BTRFS_BUILD_VERSION
);
271 static const char * const cmd_sync_usage
[] = {
272 "btrfs filesystem sync <path>",
273 "Force a sync on a filesystem",
277 static int cmd_sync(int argc
, char **argv
)
282 if (check_argc_exact(argc
, 2))
283 usage(cmd_sync_usage
);
287 fd
= open_file_or_dir(path
);
289 fprintf(stderr
, "ERROR: can't access to '%s'\n", path
);
293 printf("FSSync '%s'\n", path
);
294 res
= ioctl(fd
, BTRFS_IOC_SYNC
);
298 fprintf(stderr
, "ERROR: unable to fs-syncing '%s' - %s\n",
306 static u64
parse_size(char *s
)
312 if (!isdigit(s
[len
- 1])) {
313 c
= tolower(s
[len
- 1]);
324 fprintf(stderr
, "Unknown size descriptor %c\n", c
);
329 return atoll(s
) * mult
;
332 static int parse_compress_type(char *s
)
334 if (strcmp(optarg
, "zlib") == 0)
335 return BTRFS_COMPRESS_ZLIB
;
336 else if (strcmp(optarg
, "lzo") == 0)
337 return BTRFS_COMPRESS_LZO
;
339 fprintf(stderr
, "Unknown compress type %s\n", s
);
344 static const char * const cmd_defrag_usage
[] = {
345 "btrfs filesystem defragment [options] <file>|<dir> [<file>|<dir>...]",
346 "Defragment a file or a directory",
349 "-c[zlib,lzo] compress the file while defragmenting",
350 "-f flush data to disk immediately after defragmenting",
351 "-s start defragment only from byte onward",
352 "-l len defragment only up to len bytes",
353 "-t size minimal size of file to be considered for defragmenting",
357 static int cmd_defrag(int argc
, char **argv
)
369 struct btrfs_ioctl_defrag_range_args range
;
371 int compress_type
= BTRFS_COMPRESS_NONE
;
375 int c
= getopt(argc
, argv
, "vc::fs:l:t:");
381 compress_type
= BTRFS_COMPRESS_ZLIB
;
383 compress_type
= parse_compress_type(optarg
);
394 start
= parse_size(optarg
);
398 len
= parse_size(optarg
);
402 thresh
= parse_size(optarg
);
406 usage(cmd_defrag_usage
);
410 if (check_argc_min(argc
- optind
, 1))
411 usage(cmd_defrag_usage
);
413 memset(&range
, 0, sizeof(range
));
416 range
.extent_thresh
= thresh
;
418 range
.flags
|= BTRFS_DEFRAG_RANGE_COMPRESS
;
419 range
.compress_type
= compress_type
;
422 range
.flags
|= BTRFS_DEFRAG_RANGE_START_IO
;
424 for (i
= optind
; i
< argc
; i
++) {
426 printf("%s\n", argv
[i
]);
427 fd
= open_file_or_dir(argv
[i
]);
429 fprintf(stderr
, "failed to open %s\n", argv
[i
]);
435 ret
= ioctl(fd
, BTRFS_IOC_DEFRAG
, NULL
);
438 ret
= ioctl(fd
, BTRFS_IOC_DEFRAG_RANGE
, &range
);
439 if (ret
&& errno
== ENOTTY
) {
440 fprintf(stderr
, "ERROR: defrag range ioctl not "
441 "supported in this kernel, please try "
442 "without any options.\n");
449 fprintf(stderr
, "ERROR: defrag failed on %s - %s\n",
450 argv
[i
], strerror(e
));
456 printf("%s\n", BTRFS_BUILD_VERSION
);
458 fprintf(stderr
, "total %d failures\n", errors
);
465 static const char * const cmd_resize_usage
[] = {
466 "btrfs filesystem resize [devid:][+/-]<newsize>[gkm]|[devid:]max <path>",
467 "Resize a filesystem",
468 "If 'max' is passed, the filesystem will occupy all available space",
469 "on the device 'devid'.",
473 static int cmd_resize(int argc
, char **argv
)
475 struct btrfs_ioctl_vol_args args
;
479 if (check_argc_exact(argc
, 3))
480 usage(cmd_resize_usage
);
485 fd
= open_file_or_dir(path
);
487 fprintf(stderr
, "ERROR: can't access to '%s'\n", path
);
490 len
= strlen(amount
);
491 if (len
== 0 || len
>= BTRFS_VOL_NAME_MAX
) {
492 fprintf(stderr
, "ERROR: size value too long ('%s)\n",
497 printf("Resize '%s' of '%s'\n", path
, amount
);
498 strncpy(args
.name
, amount
, BTRFS_PATH_NAME_MAX
);
499 args
.name
[BTRFS_PATH_NAME_MAX
-1] = 0;
500 res
= ioctl(fd
, BTRFS_IOC_RESIZE
, &args
);
504 fprintf(stderr
, "ERROR: unable to resize '%s' - %s\n",
511 static const char * const cmd_label_usage
[] = {
512 "btrfs filesystem label <device> [<newlabel>]",
513 "Get or change the label of an unmounted filesystem",
514 "With one argument, get the label of filesystem on <device>.",
515 "If <newlabel> is passed, set the filesystem label to <newlabel>.",
519 static int cmd_label(int argc
, char **argv
)
521 if (check_argc_min(argc
, 2) || check_argc_max(argc
, 3))
522 usage(cmd_label_usage
);
525 return set_label(argv
[1], argv
[2]);
527 return get_label(argv
[1]);
530 const struct cmd_group filesystem_cmd_group
= {
531 filesystem_cmd_group_usage
, NULL
, {
532 { "df", cmd_df
, cmd_df_usage
, NULL
, 0 },
533 { "show", cmd_show
, cmd_show_usage
, NULL
, 0 },
534 { "sync", cmd_sync
, cmd_sync_usage
, NULL
, 0 },
535 { "defragment", cmd_defrag
, cmd_defrag_usage
, NULL
, 0 },
536 { "balance", cmd_balance
, NULL
, &balance_cmd_group
, 1 },
537 { "resize", cmd_resize
, cmd_resize_usage
, NULL
, 0 },
538 { "label", cmd_label
, cmd_label_usage
, NULL
, 0 },
543 int cmd_filesystem(int argc
, char **argv
)
545 return handle_command_group(&filesystem_cmd_group
, argc
, argv
);