btrfs-progs: split unit related helpers from utils.c

Signed-off-by: David Sterba <dsterba@suse.com>
This commit is contained in:
David Sterba 2021-04-29 23:43:24 +02:00
parent 77aca786ba
commit d591cd7c08
19 changed files with 333 additions and 279 deletions

View file

@ -174,7 +174,7 @@ libbtrfs_objects = common/send-stream.o common/send-utils.o kernel-lib/rbtree.o
common/device-scan.o common/path-utils.o \
common/utils.o libbtrfsutil/subvolume.o libbtrfsutil/stubs.o \
crypto/hash.o crypto/xxhash.o $(CRYPTO_OBJECTS) \
common/open-utils.o
common/open-utils.o common/units.o
libbtrfs_headers = common/send-stream.h common/send-utils.h send.h kernel-lib/rbtree.h btrfs-list.h \
crypto/crc32c.h kernel-lib/list.h kerncompat.h \
kernel-lib/radix-tree.h kernel-lib/sizes.h kernel-lib/raid56.h \

View file

@ -39,6 +39,7 @@
#include "common/device-scan.h"
#include "common/format-output.h"
#include "common/open-utils.h"
#include "common/units.h"
#include "mkfs/common.h"
static const char * const device_cmd_group_usage[] = {

View file

@ -40,6 +40,7 @@
#include "kernel-lib/rbtree.h"
#include "kernel-lib/interval_tree_generic.h"
#include "common/open-utils.h"
#include "common/units.h"
#include "common/help.h"
#include "common/fsfeatures.h"

View file

@ -33,6 +33,7 @@
#include "cmds/commands.h"
#include "kernel-shared/disk-io.h"
#include "common/open-utils.h"
#include "common/units.h"
#include "version.h"
#include "common/help.h"
#include "common/device-utils.h"

View file

@ -40,6 +40,7 @@
#include "kernel-lib/list_sort.h"
#include "kernel-shared/disk-io.h"
#include "common/help.h"
#include "common/units.h"
#include "common/fsfeatures.h"
#include "common/path-utils.h"
#include "common/device-scan.h"

View file

@ -37,6 +37,7 @@
#include "cmds/commands.h"
#include "common/help.h"
#include "common/open-utils.h"
#include "common/units.h"
static int verbose = 0;
static int no_pretty = 0;

View file

@ -33,6 +33,7 @@
#include "btrfs-list.h"
#include "common/help.h"
#include "common/open-utils.h"
#include "common/units.h"
static const char * const inspect_cmd_group_usage[] = {
"btrfs inspect-internal <command> <args>",

View file

@ -29,6 +29,7 @@
#include "qgroup.h"
#include "common/utils.h"
#include "common/help.h"
#include "common/units.h"
static const char * const qgroup_cmd_group_usage[] = {
"btrfs qgroup <command> [options] <path>",

View file

@ -42,6 +42,7 @@
#include "kernel-shared/volumes.h"
#include "kernel-shared/disk-io.h"
#include "common/open-utils.h"
#include "common/units.h"
#include "cmds/commands.h"
#include "common/help.h"

View file

@ -42,6 +42,7 @@
#include "common/path-utils.h"
#include "common/device-scan.h"
#include "common/open-utils.h"
#include "common/units.h"
static int wait_for_subvolume_cleaning(int fd, size_t count, uint64_t *ids,
int sleep_interval)

View file

@ -32,6 +32,7 @@
#include "common/utils.h"
#include "common/defs.h"
#include "common/open-utils.h"
#include "common/units.h"
#include "kernel-shared/ctree.h"
#include "kernel-shared/volumes.h"
#include "kernel-shared/disk-io.h"

View file

@ -31,6 +31,7 @@
#include "common/internal.h"
#include "common/messages.h"
#include "common/utils.h"
#include "common/units.h"
#ifndef BLKDISCARD
#define BLKDISCARD _IO(0x12,119)

View file

@ -20,6 +20,7 @@
#include "common/defs.h"
#include "common/format-output.h"
#include "common/utils.h"
#include "common/units.h"
#include "cmds/commands.h"
static void print_uuid(const u8 *uuid)

268
common/units.c Normal file
View file

@ -0,0 +1,268 @@
/*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public
* License v2 as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public
* License along with this program; if not, write to the
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
* Boston, MA 021110-1307, USA.
*/
#include "common/units.h"
/*
* Note: this function uses a static per-thread buffer. Do not call this
* function more than 10 times within one argument list!
*/
const char *pretty_size_mode(u64 size, unsigned mode)
{
static __thread int ps_index = 0;
static __thread char ps_array[10][32];
char *ret;
ret = ps_array[ps_index];
ps_index++;
ps_index %= 10;
(void)pretty_size_snprintf(size, ret, 32, mode);
return ret;
}
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"};
int pretty_size_snprintf(u64 size, char *str, size_t str_size, unsigned unit_mode)
{
int num_divs;
float fraction;
u64 base = 0;
int mult = 0;
const char** suffix = NULL;
u64 last_size;
int negative;
if (str_size == 0)
return 0;
negative = !!(unit_mode & UNITS_NEGATIVE);
unit_mode &= ~UNITS_NEGATIVE;
if ((unit_mode & ~UNITS_MODE_MASK) == UNITS_RAW) {
if (negative)
snprintf(str, str_size, "%lld", size);
else
snprintf(str, str_size, "%llu", size);
return 0;
}
if ((unit_mode & ~UNITS_MODE_MASK) == UNITS_BINARY) {
base = 1024;
mult = 1024;
suffix = unit_suffix_binary;
} 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 %u\n",
unit_mode);
assert(0);
return -1;
}
num_divs = 0;
last_size = size;
switch (unit_mode & UNITS_MODE_MASK) {
case UNITS_TBYTES:
base *= mult;
num_divs++;
/* fallthrough */
case UNITS_GBYTES:
base *= mult;
num_divs++;
/* fallthrough */
case UNITS_MBYTES:
base *= mult;
num_divs++;
/* fallthrough */
case UNITS_KBYTES:
num_divs++;
break;
case UNITS_BYTES:
base = 1;
num_divs = 0;
break;
default:
if (negative) {
s64 ssize = (s64)size;
s64 last_ssize = ssize;
while ((ssize < 0 ? -ssize : ssize) >= mult) {
last_ssize = ssize;
ssize /= mult;
num_divs++;
}
last_size = (u64)last_ssize;
} else {
while (size >= mult) {
last_size = size;
size /= mult;
num_divs++;
}
}
/*
* If the value is smaller than base, we didn't do any
* division, in that case, base should be 1, not original
* base, or the unit will be wrong
*/
if (num_divs == 0)
base = 1;
}
if (num_divs >= ARRAY_SIZE(unit_suffix_binary)) {
str[0] = '\0';
printf("INTERNAL ERROR: unsupported unit suffix, index %d\n",
num_divs);
assert(0);
return -1;
}
if (negative) {
fraction = (float)(s64)last_size / base;
} else {
fraction = (float)last_size / base;
}
return snprintf(str, str_size, "%.2f%s", fraction, suffix[num_divs]);
}
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;
}
unsigned int get_unit_mode_from_arg(int *argc, char *argv[], int df_mode)
{
unsigned int unit_mode = UNITS_DEFAULT;
int arg_i;
int arg_end;
for (arg_i = 0; arg_i < *argc; arg_i++) {
if (!strcmp(argv[arg_i], "--"))
break;
if (!strcmp(argv[arg_i], "--raw")) {
unit_mode = UNITS_RAW;
argv[arg_i] = NULL;
continue;
}
if (!strcmp(argv[arg_i], "--human-readable")) {
unit_mode = UNITS_HUMAN_BINARY;
argv[arg_i] = NULL;
continue;
}
if (!strcmp(argv[arg_i], "--iec")) {
units_set_mode(&unit_mode, UNITS_BINARY);
argv[arg_i] = NULL;
continue;
}
if (!strcmp(argv[arg_i], "--si")) {
units_set_mode(&unit_mode, UNITS_DECIMAL);
argv[arg_i] = NULL;
continue;
}
if (!strcmp(argv[arg_i], "--kbytes")) {
units_set_base(&unit_mode, UNITS_KBYTES);
argv[arg_i] = NULL;
continue;
}
if (!strcmp(argv[arg_i], "--mbytes")) {
units_set_base(&unit_mode, UNITS_MBYTES);
argv[arg_i] = NULL;
continue;
}
if (!strcmp(argv[arg_i], "--gbytes")) {
units_set_base(&unit_mode, UNITS_GBYTES);
argv[arg_i] = NULL;
continue;
}
if (!strcmp(argv[arg_i], "--tbytes")) {
units_set_base(&unit_mode, UNITS_TBYTES);
argv[arg_i] = NULL;
continue;
}
if (!df_mode)
continue;
if (!strcmp(argv[arg_i], "-b")) {
unit_mode = UNITS_RAW;
argv[arg_i] = NULL;
continue;
}
if (!strcmp(argv[arg_i], "-h")) {
unit_mode = UNITS_HUMAN_BINARY;
argv[arg_i] = NULL;
continue;
}
if (!strcmp(argv[arg_i], "-H")) {
unit_mode = UNITS_HUMAN_DECIMAL;
argv[arg_i] = NULL;
continue;
}
if (!strcmp(argv[arg_i], "-k")) {
units_set_base(&unit_mode, UNITS_KBYTES);
argv[arg_i] = NULL;
continue;
}
if (!strcmp(argv[arg_i], "-m")) {
units_set_base(&unit_mode, UNITS_MBYTES);
argv[arg_i] = NULL;
continue;
}
if (!strcmp(argv[arg_i], "-g")) {
units_set_base(&unit_mode, UNITS_GBYTES);
argv[arg_i] = NULL;
continue;
}
if (!strcmp(argv[arg_i], "-t")) {
units_set_base(&unit_mode, UNITS_TBYTES);
argv[arg_i] = NULL;
continue;
}
}
for (arg_i = 0, arg_end = 0; arg_i < *argc; arg_i++) {
if (!argv[arg_i])
continue;
argv[arg_end] = argv[arg_i];
arg_end++;
}
*argc = arg_end;
return unit_mode;
}

50
common/units.h Normal file
View file

@ -0,0 +1,50 @@
/*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public
* License v2 as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public
* License along with this program; if not, write to the
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
* Boston, MA 021110-1307, USA.
*/
#ifndef __BTRFS_UNITS_H__
#define __BTRFS_UNITS_H__
#include "kerncompat.h"
/*
* Output modes of size
*/
#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)
/* Interpret the u64 value as s64 */
#define UNITS_NEGATIVE (4U << 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)
const char *pretty_size_mode(u64 size, unsigned mode);
int pretty_size_snprintf(u64 size, char *str, size_t str_size, unsigned unit_mode);
#define pretty_size(size) pretty_size_mode(size, UNITS_DEFAULT)
void units_set_mode(unsigned *units, unsigned mode);
void units_set_base(unsigned *units, unsigned base);
unsigned int get_unit_mode_from_arg(int *argc, char *argv[], int df_mode);
#endif

View file

@ -103,137 +103,6 @@ struct pending_dir {
char name[PATH_MAX];
};
/*
* Note: this function uses a static per-thread buffer. Do not call this
* function more than 10 times within one argument list!
*/
const char *pretty_size_mode(u64 size, unsigned mode)
{
static __thread int ps_index = 0;
static __thread char ps_array[10][32];
char *ret;
ret = ps_array[ps_index];
ps_index++;
ps_index %= 10;
(void)pretty_size_snprintf(size, ret, 32, mode);
return ret;
}
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"};
int pretty_size_snprintf(u64 size, char *str, size_t str_size, unsigned unit_mode)
{
int num_divs;
float fraction;
u64 base = 0;
int mult = 0;
const char** suffix = NULL;
u64 last_size;
int negative;
if (str_size == 0)
return 0;
negative = !!(unit_mode & UNITS_NEGATIVE);
unit_mode &= ~UNITS_NEGATIVE;
if ((unit_mode & ~UNITS_MODE_MASK) == UNITS_RAW) {
if (negative)
snprintf(str, str_size, "%lld", size);
else
snprintf(str, str_size, "%llu", size);
return 0;
}
if ((unit_mode & ~UNITS_MODE_MASK) == UNITS_BINARY) {
base = 1024;
mult = 1024;
suffix = unit_suffix_binary;
} 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 %u\n",
unit_mode);
assert(0);
return -1;
}
num_divs = 0;
last_size = size;
switch (unit_mode & UNITS_MODE_MASK) {
case UNITS_TBYTES:
base *= mult;
num_divs++;
/* fallthrough */
case UNITS_GBYTES:
base *= mult;
num_divs++;
/* fallthrough */
case UNITS_MBYTES:
base *= mult;
num_divs++;
/* fallthrough */
case UNITS_KBYTES:
num_divs++;
break;
case UNITS_BYTES:
base = 1;
num_divs = 0;
break;
default:
if (negative) {
s64 ssize = (s64)size;
s64 last_ssize = ssize;
while ((ssize < 0 ? -ssize : ssize) >= mult) {
last_ssize = ssize;
ssize /= mult;
num_divs++;
}
last_size = (u64)last_ssize;
} else {
while (size >= mult) {
last_size = size;
size /= mult;
num_divs++;
}
}
/*
* If the value is smaller than base, we didn't do any
* division, in that case, base should be 1, not original
* base, or the unit will be wrong
*/
if (num_divs == 0)
base = 1;
}
if (num_divs >= ARRAY_SIZE(unit_suffix_binary)) {
str[0] = '\0';
printf("INTERNAL ERROR: unsupported unit suffix, index %d\n",
num_divs);
assert(0);
return -1;
}
if (negative) {
fraction = (float)(s64)last_size / base;
} else {
fraction = (float)last_size / base;
}
return snprintf(str, str_size, "%.2f%s", fraction, suffix[num_divs]);
}
/*
* Checks to make sure that the label matches our requirements.
* Returns:
@ -1312,20 +1181,6 @@ int find_mount_root(const char *path, char **mount_root)
return ret;
}
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;
}
int find_next_key(struct btrfs_path *path, struct btrfs_key *key)
{
int level;
@ -1430,111 +1285,6 @@ int btrfs_tree_search2_ioctl_supported(int fd)
return ret;
}
unsigned int get_unit_mode_from_arg(int *argc, char *argv[], int df_mode)
{
unsigned int unit_mode = UNITS_DEFAULT;
int arg_i;
int arg_end;
for (arg_i = 0; arg_i < *argc; arg_i++) {
if (!strcmp(argv[arg_i], "--"))
break;
if (!strcmp(argv[arg_i], "--raw")) {
unit_mode = UNITS_RAW;
argv[arg_i] = NULL;
continue;
}
if (!strcmp(argv[arg_i], "--human-readable")) {
unit_mode = UNITS_HUMAN_BINARY;
argv[arg_i] = NULL;
continue;
}
if (!strcmp(argv[arg_i], "--iec")) {
units_set_mode(&unit_mode, UNITS_BINARY);
argv[arg_i] = NULL;
continue;
}
if (!strcmp(argv[arg_i], "--si")) {
units_set_mode(&unit_mode, UNITS_DECIMAL);
argv[arg_i] = NULL;
continue;
}
if (!strcmp(argv[arg_i], "--kbytes")) {
units_set_base(&unit_mode, UNITS_KBYTES);
argv[arg_i] = NULL;
continue;
}
if (!strcmp(argv[arg_i], "--mbytes")) {
units_set_base(&unit_mode, UNITS_MBYTES);
argv[arg_i] = NULL;
continue;
}
if (!strcmp(argv[arg_i], "--gbytes")) {
units_set_base(&unit_mode, UNITS_GBYTES);
argv[arg_i] = NULL;
continue;
}
if (!strcmp(argv[arg_i], "--tbytes")) {
units_set_base(&unit_mode, UNITS_TBYTES);
argv[arg_i] = NULL;
continue;
}
if (!df_mode)
continue;
if (!strcmp(argv[arg_i], "-b")) {
unit_mode = UNITS_RAW;
argv[arg_i] = NULL;
continue;
}
if (!strcmp(argv[arg_i], "-h")) {
unit_mode = UNITS_HUMAN_BINARY;
argv[arg_i] = NULL;
continue;
}
if (!strcmp(argv[arg_i], "-H")) {
unit_mode = UNITS_HUMAN_DECIMAL;
argv[arg_i] = NULL;
continue;
}
if (!strcmp(argv[arg_i], "-k")) {
units_set_base(&unit_mode, UNITS_KBYTES);
argv[arg_i] = NULL;
continue;
}
if (!strcmp(argv[arg_i], "-m")) {
units_set_base(&unit_mode, UNITS_MBYTES);
argv[arg_i] = NULL;
continue;
}
if (!strcmp(argv[arg_i], "-g")) {
units_set_base(&unit_mode, UNITS_GBYTES);
argv[arg_i] = NULL;
continue;
}
if (!strcmp(argv[arg_i], "-t")) {
units_set_base(&unit_mode, UNITS_TBYTES);
argv[arg_i] = NULL;
continue;
}
}
for (arg_i = 0, arg_end = 0; arg_i < *argc; arg_i++) {
if (!argv[arg_i])
continue;
argv[arg_end] = argv[arg_i];
arg_end++;
}
*argc = arg_end;
return unit_mode;
}
u64 div_factor(u64 num, int factor)
{
if (factor == 10)

View file

@ -31,27 +31,6 @@
#include "ioctl.h"
#include "common/fsfeatures.h"
/*
* Output modes of size
*/
#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)
/* Interpret the u64 value as s64 */
#define UNITS_NEGATIVE (4U << 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)
enum exclusive_operation {
BTRFS_EXCLOP_NONE,
BTRFS_EXCLOP_BALANCE,
@ -63,14 +42,8 @@ enum exclusive_operation {
BTRFS_EXCLOP_UNKNOWN = -1,
};
void units_set_mode(unsigned *units, unsigned mode);
void units_set_base(unsigned *units, unsigned base);
int btrfs_make_root_dir(struct btrfs_trans_handle *trans,
struct btrfs_root *root, u64 objectid);
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)
const char *pretty_size_mode(u64 size, unsigned mode);
enum btrfs_csum_type parse_csum_type(const char *s);
u64 parse_size_from_string(const char *s);
@ -112,7 +85,6 @@ u64 div_factor(u64 num, int factor);
int btrfs_tree_search2_ioctl_supported(int fd);
unsigned int get_unit_mode_from_arg(int *argc, char *argv[], int df_mode);
int string_is_numerical(const char *str);
int prefixcmp(const char *str, const char *prefix);

View file

@ -48,6 +48,7 @@
#include "mkfs/rootdir.h"
#include "common/fsfeatures.h"
#include "common/box.h"
#include "common/units.h"
#include "check/qgroup-verify.h"
static int verbose = 1;

View file

@ -21,6 +21,7 @@
#include "kernel-shared/ctree.h"
#include "ioctl.h"
#include "common/utils.h"
#include "common/units.h"
#include <errno.h>
#define BTRFS_QGROUP_NFILTERS_INCREASE (2 * BTRFS_QGROUP_FILTER_MAX)