summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Documentation/btrfs-filesystem.txt25
-rw-r--r--cmds-filesystem.c79
-rw-r--r--utils.c52
-rw-r--r--utils.h30
4 files changed, 155 insertions, 31 deletions
diff --git a/Documentation/btrfs-filesystem.txt b/Documentation/btrfs-filesystem.txt
index b0d5820e..6e63d2c9 100644
--- a/Documentation/btrfs-filesystem.txt
+++ b/Documentation/btrfs-filesystem.txt
@@ -17,8 +17,31 @@ resizing, defragment.
SUBCOMMAND
----------
-*df* <path> [<path>...]::
+*df* [options] <path>::
Show space usage information for a mount point.
++
+`Options`
++
+-b|--raw::::
+raw numbers in bytes, without the 'B' suffix
+-h::::
+print human friendly numbers, base 1024, this is the default
+-H::::
+print human friendly numbers, base 1000
+--iec::::
+select the 1024 base for the following options, according to the IEC standard
+--si::::
+select the 1000 base for the following options, according to the SI standard
+-k|--kbytes::::
+show sizes in KiB, or kB with --si
+-m|--mbytes::::
+show sizes in MiB, or mB with --si
+-g|--gbytes::::
+show sizes in GiB, or gB with --si
+-t|--tbytes::::
+show sizes in TiB, or tB with --si
+
+If conflicting options are passed, the last one takes precedence.
*show* [--mounted|--all-devices|<path>|<uuid>|<device>|<label>]::
Show the btrfs filesystem with some additional info.
diff --git a/cmds-filesystem.c b/cmds-filesystem.c
index f5439145..bb5881ed 100644
--- a/cmds-filesystem.c
+++ b/cmds-filesystem.c
@@ -113,9 +113,18 @@ static const char * const filesystem_cmd_group_usage[] = {
};
static const char * const cmd_df_usage[] = {
- "btrfs filesystem df <path>",
- "Show space usage information for a mount point",
- NULL
+ "btrfs filesystem df [options] <path>",
+ "Show space usage information for a mount point",
+ "-b|--raw raw numbers in bytes",
+ "-h human friendly numbers, base 1024 (default)",
+ "-H human friendly numbers, base 1000",
+ "--iec use 1024 as a base (KiB, MiB, GiB, TiB)",
+ "--si use 1000 as a base (kB, mB, gB, tB)",
+ "-k|--kbytes show sizes in KiB, or kB with --si",
+ "-m|--mbytes show sizes in MiB, or mB with --si",
+ "-g|--gbytes show sizes in GiB, or gB with --si",
+ "-t|--tbytes show sizes in TiB, or tB with --si",
+ NULL
};
static char *group_type_str(u64 flag)
@@ -209,7 +218,7 @@ static int get_df(int fd, struct btrfs_ioctl_space_args **sargs_ret)
return 0;
}
-static void print_df(struct btrfs_ioctl_space_args *sargs)
+static void print_df(struct btrfs_ioctl_space_args *sargs, unsigned unit_mode)
{
u64 i;
struct btrfs_ioctl_space_info *sp = sargs->spaces;
@@ -218,8 +227,8 @@ static void print_df(struct btrfs_ioctl_space_args *sargs)
printf("%s, %s: total=%s, used=%s\n",
group_type_str(sp->flags),
group_profile_str(sp->flags),
- pretty_size(sp->total_bytes),
- pretty_size(sp->used_bytes));
+ pretty_size_mode(sp->total_bytes, unit_mode),
+ pretty_size_mode(sp->used_bytes, unit_mode));
}
}
@@ -229,12 +238,62 @@ static int cmd_df(int argc, char **argv)
int ret;
int fd;
char *path;
- DIR *dirstream = NULL;
+ DIR *dirstream = NULL;
+ unsigned unit_mode = UNITS_DEFAULT;
- if (check_argc_exact(argc, 2))
+ optind = 1;
+ while (1) {
+ int long_index;
+ static const struct option long_options[] = {
+ { "raw", no_argument, NULL, 'b'},
+ { "kbytes", no_argument, NULL, 'k'},
+ { "mbytes", no_argument, NULL, 'm'},
+ { "gbytes", no_argument, NULL, 'g'},
+ { "tbytes", no_argument, NULL, 't'},
+ { "si", no_argument, NULL, 256},
+ { "iec", no_argument, NULL, 257},
+ };
+ int c = getopt_long(argc, argv, "bhHkmgt", long_options,
+ &long_index);
+ if (c < 0)
+ break;
+ switch (c) {
+ case 'b':
+ unit_mode = UNITS_RAW;
+ break;
+ case 'k':
+ units_set_base(&unit_mode, UNITS_KBYTES);
+ break;
+ case 'm':
+ units_set_base(&unit_mode, UNITS_MBYTES);
+ break;
+ case 'g':
+ units_set_base(&unit_mode, UNITS_GBYTES);
+ break;
+ case 't':
+ units_set_base(&unit_mode, UNITS_TBYTES);
+ break;
+ case 'h':
+ unit_mode = UNITS_HUMAN_BINARY;
+ break;
+ case 'H':
+ unit_mode = UNITS_HUMAN_DECIMAL;
+ break;
+ case 256:
+ units_set_mode(&unit_mode, UNITS_DECIMAL);
+ break;
+ case 257:
+ units_set_mode(&unit_mode, UNITS_BINARY);
+ break;
+ default:
+ usage(cmd_df_usage);
+ }
+ }
+
+ if (check_argc_max(argc, optind + 1))
usage(cmd_df_usage);
- path = argv[1];
+ path = argv[optind];
fd = open_file_or_dir(path, &dirstream);
if (fd < 0) {
@@ -244,7 +303,7 @@ static int cmd_df(int argc, char **argv)
ret = get_df(fd, &sargs);
if (ret == 0) {
- print_df(sargs);
+ print_df(sargs, unit_mode);
free(sargs);
} else {
fprintf(stderr, "ERROR: get_df failed %s\n", strerror(-ret));
diff --git a/utils.c b/utils.c
index bdb73999..e86292ac 100644
--- a/utils.c
+++ b/utils.c
@@ -1297,35 +1297,38 @@ out:
static const char* unit_suffix_binary[] =
{ "B", "KiB", "MiB", "GiB", "TiB", "PiB", "EiB"};
static const char* unit_suffix_decimal[] =
- { "B", "KB", "MB", "GB", "TB", "PB", "EB"};
+ { "B", "kB", "mB", "gB", "tB", "pB", "eB"};
-int pretty_size_snprintf(u64 size, char *str, size_t str_size, int unit_mode)
+int pretty_size_snprintf(u64 size, char *str, size_t str_size, unsigned unit_mode)
{
int num_divs;
float fraction;
- int base = 0;
+ u64 base = 0;
+ int mult = 0;
const char** suffix = NULL;
u64 last_size;
if (str_size == 0)
return 0;
- if (unit_mode == UNITS_RAW) {
+ if ((unit_mode & ~UNITS_MODE_MASK) == UNITS_RAW) {
snprintf(str, str_size, "%llu", size);
return 0;
}
- if (unit_mode == UNITS_BINARY) {
+ if ((unit_mode & ~UNITS_MODE_MASK) == UNITS_BINARY) {
base = 1024;
+ mult = 1024;
suffix = unit_suffix_binary;
- } else if (unit_mode == UNITS_DECIMAL) {
+ } else if ((unit_mode & ~UNITS_MODE_MASK) == UNITS_DECIMAL) {
base = 1000;
+ mult = 1000;
suffix = unit_suffix_decimal;
}
/* Unknown mode */
if (!base) {
- fprintf(stderr, "INTERNAL ERROR: unknown unit base, mode %d",
+ fprintf(stderr, "INTERNAL ERROR: unknown unit base, mode %d\n",
unit_mode);
assert(0);
return -1;
@@ -1333,11 +1336,22 @@ int pretty_size_snprintf(u64 size, char *str, size_t str_size, int unit_mode)
num_divs = 0;
last_size = size;
-
- while (size >= base) {
- last_size = size;
- size /= base;
- num_divs++;
+ switch (unit_mode & UNITS_MODE_MASK) {
+ case UNITS_TBYTES: base *= mult; num_divs++;
+ case UNITS_GBYTES: base *= mult; num_divs++;
+ case UNITS_MBYTES: base *= mult; num_divs++;
+ case UNITS_KBYTES: num_divs++;
+ break;
+ case UNITS_BYTES:
+ base = 1;
+ num_divs = 0;
+ break;
+ default:
+ while (size >= mult) {
+ last_size = size;
+ size /= mult;
+ num_divs++;
+ }
}
if (num_divs >= ARRAY_SIZE(unit_suffix_binary)) {
@@ -2377,3 +2391,17 @@ int test_isdir(const char *path)
return S_ISDIR(st.st_mode);
}
+
+void units_set_mode(unsigned *units, unsigned mode)
+{
+ unsigned base = *units & UNITS_MODE_MASK;
+
+ *units = base | mode;
+}
+
+void units_set_base(unsigned *units, unsigned base)
+{
+ unsigned mode = *units & ~UNITS_MODE_MASK;
+
+ *units = base | mode;
+}
diff --git a/utils.h b/utils.h
index e2b1ba80..aed03f23 100644
--- a/utils.h
+++ b/utils.h
@@ -48,12 +48,26 @@ void fixup_argv0(char **argv, const char *token);
void set_argv0(char **argv);
/*
- * Output mode of byte units
+ * Output modes of size
*/
-#define UNITS_RAW (1)
-#define UNITS_BINARY (2)
-#define UNITS_DECIMAL (3)
-#define UNITS_HUMAN UNITS_BINARY
+#define UNITS_RESERVED (0)
+#define UNITS_BYTES (1)
+#define UNITS_KBYTES (2)
+#define UNITS_MBYTES (3)
+#define UNITS_GBYTES (4)
+#define UNITS_TBYTES (5)
+#define UNITS_RAW (1U << UNITS_MODE_SHIFT)
+#define UNITS_BINARY (2U << UNITS_MODE_SHIFT)
+#define UNITS_DECIMAL (3U << UNITS_MODE_SHIFT)
+#define UNITS_MODE_MASK ((1U << UNITS_MODE_SHIFT) - 1)
+#define UNITS_MODE_SHIFT (8)
+#define UNITS_HUMAN_BINARY (UNITS_BINARY)
+#define UNITS_HUMAN_DECIMAL (UNITS_DECIMAL)
+#define UNITS_HUMAN (UNITS_HUMAN_BINARY)
+#define UNITS_DEFAULT (UNITS_HUMAN)
+
+void units_set_mode(unsigned *units, unsigned mode);
+void units_set_base(unsigned *units, unsigned base);
int make_btrfs(int fd, const char *device, const char *label,
char *fs_uuid, u64 blocks[6], u64 num_bytes, u32 nodesize,
@@ -76,12 +90,12 @@ int check_mounted_where(int fd, const char *file, char *where, int size,
int btrfs_device_already_in_root(struct btrfs_root *root, int fd,
int super_offset);
-int pretty_size_snprintf(u64 size, char *str, size_t str_bytes, int unit_mode);
-#define pretty_size(size) pretty_size_mode(size, UNITS_BINARY)
+int pretty_size_snprintf(u64 size, char *str, size_t str_bytes, unsigned unit_mode);
+#define pretty_size(size) pretty_size_mode(size, UNITS_DEFAULT)
#define pretty_size_mode(size, mode) \
({ \
static __thread char _str[32]; \
- (void)pretty_size_snprintf((size), _str, sizeof(_str), mode); \
+ (void)pretty_size_snprintf((size), _str, sizeof(_str), (mode)); \
_str; \
})