btrfs-progs: convert device info to struct array
The device infos are passed as two parameters, use struct array for that. Signed-off-by: David Sterba <dsterba@suse.com>
This commit is contained in:
parent
0fdfcddac4
commit
88c25674c7
|
@ -834,25 +834,26 @@ static const char * const cmd_device_usage_usage[] = {
|
|||
|
||||
static int _cmd_device_usage(int fd, const char *path, unsigned unit_mode)
|
||||
{
|
||||
int i;
|
||||
int ret = 0;
|
||||
struct array chunkinfos = { 0 };
|
||||
struct device_info *devinfo = NULL;
|
||||
int devcount = 0;
|
||||
struct array devinfos = { 0 };
|
||||
|
||||
ret = load_chunk_and_device_info(fd, &chunkinfos, &devinfo, &devcount);
|
||||
ret = load_chunk_and_device_info(fd, &chunkinfos, &devinfos);
|
||||
if (ret)
|
||||
goto out;
|
||||
|
||||
for (i = 0; i < devcount; i++) {
|
||||
pr_verbose(LOG_DEFAULT, "%s, ID: %llu\n", devinfo[i].path, devinfo[i].devid);
|
||||
print_device_sizes(&devinfo[i], unit_mode);
|
||||
print_device_chunks(&devinfo[i], &chunkinfos, unit_mode);
|
||||
for (int i = 0; i < devinfos.length; i++) {
|
||||
const struct device_info *devinfo = devinfos.data[i];
|
||||
|
||||
pr_verbose(LOG_DEFAULT, "%s, ID: %llu\n", devinfo->path, devinfo->devid);
|
||||
print_device_sizes(devinfo, unit_mode);
|
||||
print_device_chunks(devinfo, &chunkinfos, unit_mode);
|
||||
pr_verbose(LOG_DEFAULT, "\n");
|
||||
}
|
||||
|
||||
out:
|
||||
free(devinfo);
|
||||
array_free_elements(&devinfos);
|
||||
array_free(&devinfos);
|
||||
array_free_elements(&chunkinfos);
|
||||
array_free(&chunkinfos);
|
||||
|
||||
|
|
|
@ -439,8 +439,7 @@ static u64 calc_slack_size(const struct device_info *devinfo)
|
|||
|
||||
#define MIN_UNALOCATED_THRESH SZ_16M
|
||||
static int print_filesystem_usage_overall(int fd, const struct array *chunkinfos,
|
||||
struct device_info *devinfo, int devcount,
|
||||
const char *path, unsigned unit_mode)
|
||||
const struct array *devinfos, const char *path, unsigned unit_mode)
|
||||
{
|
||||
struct btrfs_ioctl_space_args *sargs = NULL;
|
||||
char *tmp;
|
||||
|
@ -487,11 +486,13 @@ static int print_filesystem_usage_overall(int fd, const struct array *chunkinfos
|
|||
}
|
||||
|
||||
r_total_size = 0;
|
||||
for (i = 0; i < devcount; i++) {
|
||||
r_total_size += devinfo[i].size;
|
||||
r_total_slack += calc_slack_size(&devinfo[i]);
|
||||
if (!devinfo[i].device_size)
|
||||
r_total_missing += devinfo[i].size;
|
||||
for (i = 0; i < devinfos->length; i++) {
|
||||
const struct device_info *devinfo = devinfos->data[i];
|
||||
|
||||
r_total_size += devinfo->size;
|
||||
r_total_slack += calc_slack_size(devinfo);
|
||||
if (!devinfo->device_size)
|
||||
r_total_missing += devinfo->size;
|
||||
}
|
||||
|
||||
if (r_total_size == 0) {
|
||||
|
@ -666,12 +667,12 @@ exit:
|
|||
*/
|
||||
static int cmp_device_info(const void *a, const void *b)
|
||||
{
|
||||
const struct device_info *deva = a;
|
||||
const struct device_info *devb = b;
|
||||
const struct device_info * const *deva = a;
|
||||
const struct device_info * const *devb = b;
|
||||
|
||||
if (deva->devid < devb->devid)
|
||||
if ((*deva)->devid < (*devb)->devid)
|
||||
return -1;
|
||||
if (deva->devid > devb->devid)
|
||||
if ((*deva)->devid > (*devb)->devid)
|
||||
return 1;
|
||||
|
||||
return 0;
|
||||
|
@ -741,17 +742,13 @@ static int device_is_seed(int fd, const char *dev_path, u64 devid, const u8 *mnt
|
|||
/*
|
||||
* This function loads the device_info structure and put them in an array
|
||||
*/
|
||||
static int load_device_info(int fd, struct device_info **devinfo_ret,
|
||||
int *devcount_ret)
|
||||
static int load_device_info(int fd, struct array *devinfos)
|
||||
{
|
||||
int ret, i, ndevs;
|
||||
struct btrfs_ioctl_fs_info_args fi_args;
|
||||
struct btrfs_ioctl_dev_info_args dev_info;
|
||||
struct device_info *info;
|
||||
|
||||
*devcount_ret = 0;
|
||||
*devinfo_ret = NULL;
|
||||
|
||||
ret = ioctl(fd, BTRFS_IOC_FS_INFO, &fi_args);
|
||||
if (ret < 0) {
|
||||
if (errno == EPERM)
|
||||
|
@ -760,12 +757,6 @@ static int load_device_info(int fd, struct device_info **devinfo_ret,
|
|||
return 1;
|
||||
}
|
||||
|
||||
info = calloc(fi_args.num_devices, sizeof(struct device_info));
|
||||
if (!info) {
|
||||
error_msg(ERROR_MSG_MEMORY, NULL);
|
||||
return 1;
|
||||
}
|
||||
|
||||
for (i = 0, ndevs = 0 ; i <= fi_args.max_id ; i++) {
|
||||
if (ndevs >= fi_args.num_devices) {
|
||||
error("unexpected number of devices: %d >= %llu", ndevs,
|
||||
|
@ -796,16 +787,26 @@ static int load_device_info(int fd, struct device_info **devinfo_ret,
|
|||
if (!ret)
|
||||
continue;
|
||||
|
||||
info[ndevs].devid = dev_info.devid;
|
||||
info = calloc(1, sizeof(struct device_info));
|
||||
if (!info) {
|
||||
error_msg(ERROR_MSG_MEMORY, NULL);
|
||||
return 1;
|
||||
}
|
||||
ret = array_append(devinfos, info);
|
||||
if (ret < 0) {
|
||||
error_msg(ERROR_MSG_MEMORY, NULL);
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
info->devid = dev_info.devid;
|
||||
if (!dev_info.path[0]) {
|
||||
strcpy(info[ndevs].path, "missing");
|
||||
strcpy(info->path, "missing");
|
||||
} else {
|
||||
strcpy(info[ndevs].path, (char *)dev_info.path);
|
||||
info[ndevs].device_size =
|
||||
strcpy(info->path, (char *)dev_info.path);
|
||||
info->device_size =
|
||||
device_get_partition_size((const char *)dev_info.path);
|
||||
}
|
||||
info[ndevs].size = dev_info.total_bytes;
|
||||
++ndevs;
|
||||
info->size = dev_info.total_bytes;
|
||||
}
|
||||
|
||||
if (ndevs != fi_args.num_devices) {
|
||||
|
@ -814,21 +815,15 @@ static int load_device_info(int fd, struct device_info **devinfo_ret,
|
|||
goto out;
|
||||
}
|
||||
|
||||
qsort(info, fi_args.num_devices,
|
||||
sizeof(struct device_info), cmp_device_info);
|
||||
|
||||
*devcount_ret = fi_args.num_devices;
|
||||
*devinfo_ret = info;
|
||||
qsort(devinfos->data, devinfos->length, sizeof(struct device_info *), cmp_device_info);
|
||||
|
||||
return 0;
|
||||
|
||||
out:
|
||||
free(info);
|
||||
return ret;
|
||||
}
|
||||
|
||||
int load_chunk_and_device_info(int fd, struct array *chunkinfos,
|
||||
struct device_info **devinfo_ret, int *devcount_ret)
|
||||
int load_chunk_and_device_info(int fd, struct array *chunkinfos, struct array *devinfos)
|
||||
{
|
||||
int ret;
|
||||
|
||||
|
@ -840,7 +835,7 @@ int load_chunk_and_device_info(int fd, struct array *chunkinfos,
|
|||
return ret;
|
||||
}
|
||||
|
||||
ret = load_device_info(fd, devinfo_ret, devcount_ret);
|
||||
ret = load_device_info(fd, devinfos);
|
||||
if (ret == -EPERM) {
|
||||
warning(
|
||||
"cannot get filesystem info from ioctl(FS_INFO), run as root");
|
||||
|
@ -877,10 +872,10 @@ static u64 calc_chunk_size(const struct chunk_info *ci)
|
|||
static void _cmd_filesystem_usage_tabular(unsigned unit_mode,
|
||||
struct btrfs_ioctl_space_args *sargs,
|
||||
const struct array *chunkinfos,
|
||||
struct device_info *devinfo,
|
||||
int devcount)
|
||||
const struct array *devinfos)
|
||||
{
|
||||
int i;
|
||||
int devcount = devinfos->length;
|
||||
u64 total_unused = 0;
|
||||
u64 total_total = 0;
|
||||
u64 total_slack = 0;
|
||||
|
@ -944,24 +939,23 @@ static void _cmd_filesystem_usage_tabular(unsigned unit_mode,
|
|||
/* body */
|
||||
for (i = 0; i < devcount; i++) {
|
||||
int k;
|
||||
char *p;
|
||||
const char *p;
|
||||
const struct device_info *devinfo = devinfos->data[i];
|
||||
|
||||
u64 total_allocated = 0, unused;
|
||||
|
||||
p = strrchr(devinfo[i].path, '/');
|
||||
p = strrchr(devinfo->path, '/');
|
||||
if (!p)
|
||||
p = devinfo[i].path;
|
||||
p = devinfo->path;
|
||||
else
|
||||
p++;
|
||||
|
||||
table_printf(matrix, 0, vhdr_skip + i, ">%llu",
|
||||
devinfo[i].devid);
|
||||
table_printf(matrix, 1, vhdr_skip + i, "<%s",
|
||||
devinfo[i].path);
|
||||
table_printf(matrix, 0, vhdr_skip + i, ">%llu", devinfo->devid);
|
||||
table_printf(matrix, 1, vhdr_skip + i, "<%s", devinfo->path);
|
||||
|
||||
for (col = spaceinfos_col, k = 0; k < sargs->total_spaces; k++) {
|
||||
u64 flags = sargs->spaces[k].flags;
|
||||
u64 devid = devinfo[i].devid;
|
||||
u64 devid = devinfo->devid;
|
||||
u64 size = 0;
|
||||
|
||||
if (flags & BTRFS_SPACE_INFO_GLOBAL_RSV)
|
||||
|
@ -988,16 +982,14 @@ static void _cmd_filesystem_usage_tabular(unsigned unit_mode,
|
|||
col++;
|
||||
}
|
||||
|
||||
unused = device_get_partition_size(devinfo[i].path)
|
||||
- total_allocated;
|
||||
unused = devinfo[i].size - total_allocated;
|
||||
unused = device_get_partition_size(devinfo->path) - total_allocated;
|
||||
unused = devinfo->size - total_allocated;
|
||||
|
||||
table_printf(matrix, unallocated_col, vhdr_skip + i, ">%s",
|
||||
pretty_size_mode(unused, unit_mode | UNITS_NEGATIVE));
|
||||
table_printf(matrix, total_col, vhdr_skip + i, ">%s",
|
||||
pretty_size_mode(devinfo[i].size,
|
||||
unit_mode | UNITS_NEGATIVE));
|
||||
slack = calc_slack_size(&devinfo[i]);
|
||||
pretty_size_mode(devinfo->size, unit_mode | UNITS_NEGATIVE));
|
||||
slack = calc_slack_size(devinfo);
|
||||
if (slack > 0) {
|
||||
table_printf(matrix, slack_col, vhdr_skip + i, ">%s",
|
||||
pretty_size_mode(slack,
|
||||
|
@ -1007,8 +999,7 @@ static void _cmd_filesystem_usage_tabular(unsigned unit_mode,
|
|||
}
|
||||
total_unused += unused;
|
||||
total_slack += slack;
|
||||
total_total += devinfo[i].size;
|
||||
|
||||
total_total += devinfo->size;
|
||||
}
|
||||
|
||||
for (i = 0; i < spaceinfos_col; i++) {
|
||||
|
@ -1070,24 +1061,23 @@ static void _cmd_filesystem_usage_tabular(unsigned unit_mode,
|
|||
/*
|
||||
* This function prints the unused space per every disk
|
||||
*/
|
||||
static void print_unused(const struct array *chunkinfos, struct device_info *devinfo,
|
||||
int devcount, unsigned unit_mode)
|
||||
static void print_unused(const struct array *chunkinfos, const struct array *devinfos,
|
||||
unsigned unit_mode)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < devcount; i++) {
|
||||
for (int i = 0; i < devinfos->length; i++) {
|
||||
u64 total = 0;
|
||||
const struct device_info *devinfo = devinfos->data[i];
|
||||
|
||||
for (int j = 0; j < chunkinfos->length; j++) {
|
||||
const struct chunk_info *chunk = chunkinfos->data[j];
|
||||
|
||||
if (chunk->devid == devinfo[i].devid)
|
||||
if (chunk->devid == devinfo->devid)
|
||||
total += calc_chunk_size(chunk);
|
||||
}
|
||||
|
||||
pr_verbose(LOG_DEFAULT, " %s\t%10s\n",
|
||||
devinfo[i].path,
|
||||
pretty_size_mode(devinfo[i].size - total, unit_mode));
|
||||
devinfo->path,
|
||||
pretty_size_mode(devinfo->size - total, unit_mode));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1095,12 +1085,10 @@ static void print_unused(const struct array *chunkinfos, struct device_info *dev
|
|||
* This function prints the allocated chunk per every disk
|
||||
*/
|
||||
static void print_chunk_device(u64 chunk_type, const struct array *chunkinfos,
|
||||
struct device_info *devinfo, int devcount,
|
||||
unsigned unit_mode)
|
||||
const struct array *devinfos, unsigned unit_mode)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < devcount; i++) {
|
||||
for (int i = 0; i < devinfos->length; i++) {
|
||||
const struct device_info *devinfo = devinfos->data[i];
|
||||
u64 total = 0;
|
||||
|
||||
for (int j = 0; j < chunkinfos->length; j++) {
|
||||
|
@ -1108,16 +1096,15 @@ static void print_chunk_device(u64 chunk_type, const struct array *chunkinfos,
|
|||
|
||||
if (chunk->type != chunk_type)
|
||||
continue;
|
||||
if (chunk->devid != devinfo[i].devid)
|
||||
if (chunk->devid != devinfo->devid)
|
||||
continue;
|
||||
|
||||
total += calc_chunk_size(chunk);
|
||||
}
|
||||
|
||||
if (total > 0)
|
||||
pr_verbose(LOG_DEFAULT, " %s\t%10s\n",
|
||||
devinfo[i].path,
|
||||
pretty_size_mode(total, unit_mode));
|
||||
pr_verbose(LOG_DEFAULT, " %s\t%10s\n", devinfo->path,
|
||||
pretty_size_mode(total, unit_mode));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1128,8 +1115,7 @@ static void print_chunk_device(u64 chunk_type, const struct array *chunkinfos,
|
|||
static void _cmd_filesystem_usage_linear(unsigned unit_mode,
|
||||
struct btrfs_ioctl_space_args *sargs,
|
||||
const struct array *chunkinfos,
|
||||
struct device_info *devinfo,
|
||||
int devcount)
|
||||
const struct array *devinfos)
|
||||
{
|
||||
int i;
|
||||
|
||||
|
@ -1153,19 +1139,19 @@ static void _cmd_filesystem_usage_linear(unsigned unit_mode,
|
|||
pretty_size_mode(sargs->spaces[i].used_bytes, unit_mode),
|
||||
100.0f * sargs->spaces[i].used_bytes /
|
||||
(sargs->spaces[i].total_bytes + 1));
|
||||
print_chunk_device(flags, chunkinfos, devinfo, devcount, unit_mode);
|
||||
print_chunk_device(flags, chunkinfos, devinfos, unit_mode);
|
||||
pr_verbose(LOG_DEFAULT, "\n");
|
||||
}
|
||||
|
||||
if (chunkinfos->length > 0) {
|
||||
pr_verbose(LOG_DEFAULT, "Unallocated:\n");
|
||||
print_unused(chunkinfos, devinfo, devcount, unit_mode | UNITS_NEGATIVE);
|
||||
print_unused(chunkinfos, devinfos, unit_mode | UNITS_NEGATIVE);
|
||||
}
|
||||
}
|
||||
|
||||
static int print_filesystem_usage_by_chunk(int fd,
|
||||
const struct array *chunkinfos,
|
||||
struct device_info *devinfo, int devcount,
|
||||
const struct array *devinfos,
|
||||
const char *path, unsigned unit_mode, int tabular)
|
||||
{
|
||||
struct btrfs_ioctl_space_args *sargs;
|
||||
|
@ -1178,11 +1164,9 @@ static int print_filesystem_usage_by_chunk(int fd,
|
|||
}
|
||||
|
||||
if (tabular)
|
||||
_cmd_filesystem_usage_tabular(unit_mode, sargs, chunkinfos,
|
||||
devinfo, devcount);
|
||||
_cmd_filesystem_usage_tabular(unit_mode, sargs, chunkinfos, devinfos);
|
||||
else
|
||||
_cmd_filesystem_usage_linear(unit_mode, sargs, chunkinfos,
|
||||
devinfo, devcount);
|
||||
_cmd_filesystem_usage_linear(unit_mode, sargs, chunkinfos, devinfos);
|
||||
|
||||
free(sargs);
|
||||
out:
|
||||
|
@ -1233,8 +1217,7 @@ static int cmd_filesystem_usage(const struct cmd_struct *cmd,
|
|||
int fd;
|
||||
DIR *dirstream = NULL;
|
||||
struct array chunkinfos = { 0 };
|
||||
struct device_info *devinfo = NULL;
|
||||
int devcount = 0;
|
||||
struct array devinfos = { 0 };
|
||||
|
||||
fd = btrfs_open_dir(argv[i], &dirstream, 1);
|
||||
if (fd < 0) {
|
||||
|
@ -1244,23 +1227,23 @@ static int cmd_filesystem_usage(const struct cmd_struct *cmd,
|
|||
if (more_than_one)
|
||||
pr_verbose(LOG_DEFAULT, "\n");
|
||||
|
||||
ret = load_chunk_and_device_info(fd, &chunkinfos,
|
||||
&devinfo, &devcount);
|
||||
ret = load_chunk_and_device_info(fd, &chunkinfos, &devinfos);
|
||||
if (ret)
|
||||
goto cleanup;
|
||||
|
||||
ret = print_filesystem_usage_overall(fd, &chunkinfos,
|
||||
devinfo, devcount, argv[i], unit_mode);
|
||||
&devinfos, argv[i], unit_mode);
|
||||
if (ret)
|
||||
goto cleanup;
|
||||
pr_verbose(LOG_DEFAULT, "\n");
|
||||
ret = print_filesystem_usage_by_chunk(fd, &chunkinfos,
|
||||
devinfo, devcount, argv[i], unit_mode, tabular);
|
||||
&devinfos, argv[i], unit_mode, tabular);
|
||||
cleanup:
|
||||
close_file_or_dir(fd, dirstream);
|
||||
array_free_elements(&chunkinfos);
|
||||
array_free(&chunkinfos);
|
||||
free(devinfo);
|
||||
array_free_elements(&devinfos);
|
||||
array_free(&devinfos);
|
||||
|
||||
if (ret)
|
||||
goto out;
|
||||
|
@ -1272,7 +1255,7 @@ out:
|
|||
}
|
||||
DEFINE_SIMPLE_COMMAND(filesystem_usage, "usage");
|
||||
|
||||
void print_device_chunks(struct device_info *devinfo,
|
||||
void print_device_chunks(const struct device_info *devinfo,
|
||||
const struct array *chunkinfos, unsigned unit_mode)
|
||||
{
|
||||
int i;
|
||||
|
@ -1324,7 +1307,7 @@ void print_device_chunks(struct device_info *devinfo,
|
|||
unit_mode | UNITS_NEGATIVE));
|
||||
}
|
||||
|
||||
void print_device_sizes(struct device_info *devinfo, unsigned unit_mode)
|
||||
void print_device_sizes(const struct device_info *devinfo, unsigned unit_mode)
|
||||
{
|
||||
pr_verbose(LOG_DEFAULT, " Device size: %*s%10s\n",
|
||||
(int)(20 - strlen("Device size")), "",
|
||||
|
|
|
@ -45,11 +45,10 @@ struct chunk_info {
|
|||
u64 num_stripes;
|
||||
};
|
||||
|
||||
int load_chunk_and_device_info(int fd, struct array *chunkinfos,
|
||||
struct device_info **devinfo_ret, int *devcount_ret);
|
||||
void print_device_chunks(struct device_info *devinfo,
|
||||
int load_chunk_and_device_info(int fd, struct array *chunkinfos, struct array *devinfos);
|
||||
void print_device_chunks(const struct device_info *devinfo,
|
||||
const struct array *chunkinfos, unsigned unit_mode);
|
||||
void print_device_sizes(struct device_info *devinfo, unsigned unit_mode);
|
||||
void print_device_sizes(const struct device_info *devinfo, unsigned unit_mode);
|
||||
int dev_to_fsid(const char *dev, u8 *fsid);
|
||||
|
||||
#endif
|
||||
|
|
Loading…
Reference in New Issue