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:
David Sterba 2023-07-17 03:23:05 +02:00
parent 0fdfcddac4
commit 88c25674c7
3 changed files with 86 additions and 103 deletions

View File

@ -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);

View File

@ -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")), "",

View File

@ -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