All of lore.kernel.org
 help / color / mirror / Atom feed
From: Roman Mamedov <rm@romanrm.net>
To: kreijack@inwind.it
Cc: kreijack@libero.it, linux-btrfs@vger.kernel.org
Subject: Re: [PATCH 5/8] Add command btrfs filesystem disk-usage
Date: Fri, 14 Feb 2014 01:28:10 +0600	[thread overview]
Message-ID: <20140214012810.26297146@natsu> (raw)
In-Reply-To: <52FD1AD6.50500@libero.it>

[-- Attachment #1: Type: text/plain, Size: 13404 bytes --]

On Thu, 13 Feb 2014 20:19:50 +0100
Goffredo Baroncelli <kreijack@libero.it> wrote:

> Signed-off-by: Goffredo Baroncelli <kreijack@inwind.it>
> ---
>  cmds-fi-disk_usage.c | 428 +++++++++++++++++++++++++++++++++++++++++++++++++++
>  cmds-fi-disk_usage.h |   3 +
>  cmds-filesystem.c    |   3 +
>  utils.c              |  63 ++++++++
>  utils.h              |   3 +
>  5 files changed, 500 insertions(+)
> 
> diff --git a/cmds-fi-disk_usage.c b/cmds-fi-disk_usage.c
> index 4012c78..16b3ab2 100644
> --- a/cmds-fi-disk_usage.c
> +++ b/cmds-fi-disk_usage.c
> @@ -20,10 +20,12 @@
>  #include <unistd.h>
>  #include <sys/ioctl.h>
>  #include <errno.h>
> +#include <stdarg.h>
>  
>  #include "utils.h"
>  #include "kerncompat.h"
>  #include "ctree.h"
> +#include "string_table.h"
>  
>  #include "commands.h"
>  
> @@ -44,6 +46,13 @@ struct chunk_info {
>  	u64	num_stripes;
>  };
>  
> +/* to store information about the disks */
> +struct disk_info {
> +	u64	devid;
> +	char	path[BTRFS_DEVICE_PATH_NAME_MAX];
> +	u64	size;
> +};
> +
>  /*
>   * Pretty print the size
>   * PAY ATTENTION: it return a statically buffer
> @@ -514,3 +523,422 @@ int cmd_filesystem_df(int argc, char **argv)
>  	return 0;
>  }
>  
> +/*
> + *  Helper to sort the disk_info structure
> + */
> +static int cmp_disk_info(const void *a, const void *b)
> +{
> +	return strcmp(((struct disk_info *)a)->path,
> +			((struct disk_info *)b)->path);
> +}
> +
> +/*
> + *  This function load the disk_info structure and put them in an array
> + */
> +static int load_disks_info(int fd,
> +			   struct disk_info **disks_info_ptr,
> +			   int *disks_info_count)
> +{
> +
> +	int ret, i, ndevs;
> +	struct btrfs_ioctl_fs_info_args fi_args;
> +	struct btrfs_ioctl_dev_info_args dev_info;
> +	struct disk_info *info;
> +
> +	*disks_info_count = 0;
> +	*disks_info_ptr = 0;
> +
> +	ret = ioctl(fd, BTRFS_IOC_FS_INFO, &fi_args);
> +	if (ret < 0) {
> +		fprintf(stderr, "ERROR: cannot get filesystem info\n");
> +		return -1;
> +	}
> +
> +	info = malloc(sizeof(struct disk_info) * fi_args.num_devices);
> +	if (!info) {
> +		fprintf(stderr, "ERROR: not enough memory\n");
> +		return -1;
> +	}
> +
> +	for (i = 0, ndevs = 0 ; i <= fi_args.max_id ; i++) {
> +
> +		BUG_ON(ndevs >= fi_args.num_devices);
> +		ret = get_device_info(fd, i, &dev_info);
> +
> +		if (ret == -ENODEV)
> +			continue;
> +		if (ret) {
> +			fprintf(stderr,
> +			    "ERROR: cannot get info about device devid=%d\n",
> +			    i);
> +			free(info);
> +			return -1;
> +		}
> +
> +		info[ndevs].devid = dev_info.devid;
> +		strcpy(info[ndevs].path, (char *)dev_info.path);
> +		info[ndevs].size = get_partition_size((char *)dev_info.path);
> +		++ndevs;
> +	}
> +
> +	BUG_ON(ndevs != fi_args.num_devices);
> +	qsort(info, fi_args.num_devices,
> +		sizeof(struct disk_info), cmp_disk_info);
> +
> +	*disks_info_count = fi_args.num_devices;
> +	*disks_info_ptr = info;
> +
> +	return 0;
> +
> +}
> +
> +/*
> + *  This function computes the size of a chunk in a disk
> + */
> +static u64 calc_chunk_size(struct chunk_info *ci)
> +{
> +	if (ci->type & BTRFS_BLOCK_GROUP_RAID0)
> +		return ci->size / ci->num_stripes;
> +	else if (ci->type & BTRFS_BLOCK_GROUP_RAID1)
> +		return ci->size ;
> +	else if (ci->type & BTRFS_BLOCK_GROUP_DUP)
> +		return ci->size ;
> +	else if (ci->type & BTRFS_BLOCK_GROUP_RAID5)
> +		return ci->size / (ci->num_stripes -1);
> +	else if (ci->type & BTRFS_BLOCK_GROUP_RAID6)
> +		return ci->size / (ci->num_stripes -2);
> +	else if (ci->type & BTRFS_BLOCK_GROUP_RAID10)
> +		return ci->size / ci->num_stripes;
> +	return ci->size;
> +}
> +
> +/*
> + *  This function print the results of the command btrfs fi disk-usage
> + *  in tabular format
> + */
> +static void _cmd_filesystem_disk_usage_tabular(int mode,
> +					struct btrfs_ioctl_space_args *sargs,
> +					struct chunk_info *chunks_info_ptr,
> +					int chunks_info_count,
> +					struct disk_info *disks_info_ptr,
> +					int disks_info_count)
> +{
> +	int i;
> +	u64 total_unused = 0;
> +	struct string_table *matrix = 0;
> +	int  ncols, nrows;
> +
> +	ncols = sargs->total_spaces + 2;
> +	nrows = 2 + 1 + disks_info_count + 1 + 2;
> +
> +	matrix = table_create(ncols, nrows);
> +	if (!matrix) {
> +		fprintf(stderr, "ERROR: not enough memory\n");
> +		return;
> +	}
> +
> +	/* header */
> +	for (i = 0; i < sargs->total_spaces; i++) {
> +		const char *description;
> +
> +		u64 flags = sargs->spaces[i].flags;
> +		description = group_type_str(flags);
> +
> +		table_printf(matrix, 1+i, 0, "<%s", description);
> +	}
> +
> +	for (i = 0; i < sargs->total_spaces; i++) {
> +		const char *r_mode;
> +
> +		u64 flags = sargs->spaces[i].flags;
> +		r_mode = group_profile_str(flags);
> +
> +		table_printf(matrix, 1+i, 1, "<%s", r_mode);
> +	}
> +
> +	table_printf(matrix, 1+sargs->total_spaces, 1, "<Unallocated");
> +
> +	/* body */
> +	for (i = 0 ; i < disks_info_count ; i++) {
> +		int k, col;
> +		char *p;
> +
> +		u64  total_allocated = 0, unused;
> +
> +		p = strrchr(disks_info_ptr[i].path, '/');
> +		if (!p)
> +			p = disks_info_ptr[i].path;
> +		else
> +			p++;
> +
> +		table_printf(matrix, 0, i+3, "<%s",
> +				disks_info_ptr[i].path);
> +
> +		for (col = 1, k = 0 ; k < sargs->total_spaces ; k++)  {
> +			u64	flags = sargs->spaces[k].flags;
> +			u64 devid = disks_info_ptr[i].devid;
> +			int	j;
> +			u64 size = 0;
> +
> +			for (j = 0 ; j < chunks_info_count ; j++) {
> +				if (chunks_info_ptr[j].type != flags )
> +						continue;
> +				if (chunks_info_ptr[j].devid != devid)
> +						continue;
> +
> +				size += calc_chunk_size(chunks_info_ptr+j);
> +			}
> +
> +			if (size)
> +				table_printf(matrix, col, i+3,
> +					">%s", df_pretty_sizes(size, mode));
> +			else
> +				table_printf(matrix, col, i+3, ">-");
> +
> +			total_allocated += size;
> +			col++;
> +		}
> +
> +		unused = get_partition_size(disks_info_ptr[i].path) -
> +				total_allocated;
> +
> +		table_printf(matrix, sargs->total_spaces + 1, i + 3,
> +			       ">%s", df_pretty_sizes(unused, mode));
> +		total_unused += unused;
> +
> +	}
> +
> +	for (i = 0; i <= sargs->total_spaces; i++)
> +		table_printf(matrix, i + 1, disks_info_count + 3, "=");
> +
> +
> +	/* footer */
> +	table_printf(matrix, 0, disks_info_count + 4, "<Total");
> +	for (i = 0; i < sargs->total_spaces; i++)
> +		table_printf(matrix, 1 + i, disks_info_count + 4,
> +			">%s",
> +			df_pretty_sizes(sargs->spaces[i].total_bytes, mode));
> +
> +	table_printf(matrix, sargs->total_spaces+1, disks_info_count+4,
> +		">%s", df_pretty_sizes(total_unused, mode));
> +
> +	table_printf(matrix, 0, disks_info_count+5, "<Used");
> +	for (i = 0; i < sargs->total_spaces; i++)
> +		table_printf(matrix, 1+i, disks_info_count+5, ">%s",
> +			df_pretty_sizes(sargs->spaces[i].used_bytes, mode));
> +
> +
> +	table_dump(matrix);
> +	table_free(matrix);
> +
> +}
> +
> +/*
> + *  This function prints the unused space per every disk
> + */
> +static void print_unused(struct chunk_info *info_ptr,
> +			  int info_count,
> +			  struct disk_info *disks_info_ptr,
> +			  int disks_info_count,
> +			  int mode)
> +{
> +	int i;
> +	for (i = 0 ; i < disks_info_count ; i++) {
> +
> +		int	j;
> +		u64	total = 0;
> +
> +		for (j = 0 ; j < info_count ; j++)
> +			if (info_ptr[j].devid == disks_info_ptr[i].devid)
> +				total += calc_chunk_size(info_ptr+j);
> +
> +		printf("   %s\t%10s\n",
> +			disks_info_ptr[i].path,
> +			df_pretty_sizes(disks_info_ptr[i].size - total, mode));
> +
> +	}
> +
> +}
> +
> +/*
> + *  This function prints the allocated chunk per every disk
> + */
> +static void print_chunk_disks(u64 chunk_type,
> +				struct chunk_info *chunks_info_ptr,
> +				int chunks_info_count,
> +				struct disk_info *disks_info_ptr,
> +				int disks_info_count,
> +				int mode)
> +{
> +	int i;
> +
> +	for (i = 0 ; i < disks_info_count ; i++) {
> +
> +		int	j;
> +		u64	total = 0;
> +
> +		for (j = 0 ; j < chunks_info_count ; j++) {
> +
> +			if (chunks_info_ptr[j].type != chunk_type)
> +				continue;
> +			if (chunks_info_ptr[j].devid != disks_info_ptr[i].devid)
> +				continue;
> +
> +			total += calc_chunk_size(&(chunks_info_ptr[j]));
> +			//total += chunks_info_ptr[j].size;
> +		}
> +
> +		if (total > 0)
> +			printf("   %s\t%10s\n",
> +				disks_info_ptr[i].path,
> +				df_pretty_sizes(total, mode));
> +	}
> +}
> +
> +/*
> + *  This function print the results of the command btrfs fi disk-usage
> + *  in linear format
> + */
> +static void _cmd_filesystem_disk_usage_linear(int mode,
> +					struct btrfs_ioctl_space_args *sargs,
> +					struct chunk_info *info_ptr,
> +					int info_count,
> +					struct disk_info *disks_info_ptr,
> +					int disks_info_count)
> +{
> +	int i;
> +
> +	for (i = 0; i < sargs->total_spaces; i++) {
> +		const char *description;
> +		const char *r_mode;
> +
> +		u64 flags = sargs->spaces[i].flags;
> +		description= group_type_str(flags);
> +		r_mode = group_profile_str(flags);
> +
> +		printf("%s,%s: Size:%s, ",
> +			description,
> +			r_mode,
> +			df_pretty_sizes(sargs->spaces[i].total_bytes ,
> +			    mode));
> +		printf("Used:%s\n",
> +			df_pretty_sizes(sargs->spaces[i].used_bytes,
> +					mode));
> +		print_chunk_disks(flags, info_ptr, info_count,
> +				disks_info_ptr, disks_info_count,
> +				mode);
> +		printf("\n");
> +
> +	}
> +
> +	printf("Unallocated:\n");
> +	print_unused(info_ptr, info_count,
> +			disks_info_ptr, disks_info_count,
> +			mode);
> +
> +
> +
> +}
> +
> +static int _cmd_filesystem_disk_usage(int fd, char *path, int mode, int tabular)
> +{
> +	struct btrfs_ioctl_space_args *sargs = 0;
> +	int info_count = 0;
> +	struct chunk_info *info_ptr = 0;
> +	struct disk_info *disks_info_ptr = 0;
> +	int disks_info_count = 0;
> +	int ret = 0;
> +
> +	if (load_chunk_info(fd, &info_ptr, &info_count) ||
> +	    load_disks_info(fd, &disks_info_ptr, &disks_info_count)) {
> +		ret = -1;
> +		goto exit;
> +	}
> +
> +	if ((sargs = load_space_info(fd, path)) == NULL) {
> +		ret = -1;
> +		goto exit;
> +	}
> +
> +	if (tabular)
> +		_cmd_filesystem_disk_usage_tabular(mode, sargs,
> +					info_ptr, info_count,
> +					disks_info_ptr, disks_info_count);
> +	else
> +		_cmd_filesystem_disk_usage_linear(mode, sargs,
> +					info_ptr, info_count,
> +					disks_info_ptr, disks_info_count);
> +
> +exit:
> +
> +	if (sargs)
> +		free(sargs);
> +	if (disks_info_ptr)
> +		free(disks_info_ptr);
> +	if (info_ptr)
> +		free(info_ptr);
> +
> +	return ret;
> +}
> +
> +const char * const cmd_filesystem_disk_usage_usage[] = {
> +	"btrfs filesystem disk-usage [-b][-t] <path> [<path>..]",
> +	"Show in which disk the chunks are allocated.",
> +	"",
> +	"-b\tSet byte as unit",
> +	"-t\tShow data in tabular format",
> +	NULL
> +};
> +
> +int cmd_filesystem_disk_usage(int argc, char **argv)
> +{
> +
> +	int	flags =	DF_HUMAN_UNIT;
> +	int	i, more_than_one = 0;
> +	int	tabular = 0;
> +
> +	optind = 1;
> +	while (1) {
> +		char	c = getopt(argc, argv, "bt");
> +		if (c < 0)
> +			break;
> +		switch (c) {
> +		case 'b':
> +			flags &= ~DF_HUMAN_UNIT;
> +			break;
> +		case 't':
> +			tabular = 1;
> +			break;
> +		default:
> +			usage(cmd_filesystem_disk_usage_usage);
> +		}
> +	}
> +
> +	if (check_argc_min(argc - optind, 1)) {
> +		usage(cmd_filesystem_disk_usage_usage);
> +		return 21;
> +	}
> +
> +	for (i = optind; i < argc ; i++) {
> +		int r, fd;
> +		DIR	*dirstream = NULL;
> +		if (more_than_one)
> +			printf("\n");
> +
> +		fd = open_file_or_dir(argv[i], &dirstream);
> +		if (fd < 0) {
> +			fprintf(stderr, "ERROR: can't access to '%s'\n",
> +				argv[1]);
> +			return 12;
> +		}
> +		r = _cmd_filesystem_disk_usage(fd, argv[i], flags, tabular);
> +		close_file_or_dir(fd, dirstream);
> +
> +		if (r)
> +			return r;
> +		more_than_one = 1;
> +
> +	}
> +
> +	return 0;
> +}
> diff --git a/cmds-fi-disk_usage.h b/cmds-fi-disk_usage.h
> index 9f68bb3..c7459b1 100644
> --- a/cmds-fi-disk_usage.h
> +++ b/cmds-fi-disk_usage.h
> @@ -22,4 +22,7 @@
>  extern const char * const cmd_filesystem_df_usage[];
>  int cmd_filesystem_df(int argc, char **argv);
>  
> +extern const char * const cmd_filesystem_disk_usage_usage[];
> +int cmd_filesystem_disk_usage(int argc, char **argv);
> +
>  #endif
> diff --git a/cmds-filesystem.c b/cmds-filesystem.c
> index fc85eef..d4cab63 100644
> --- a/cmds-filesystem.c
> +++ b/cmds-filesystem.c
> @@ -798,6 +798,9 @@ const struct cmd_group filesystem_cmd_group = {
>  		{ "balance", cmd_balance, NULL, &balance_cmd_group, 1 },
>  		{ "resize", cmd_resize, cmd_resize_usage, NULL, 0 },
>  		{ "label", cmd_label, cmd_label_usage, NULL, 0 },
> +		{ "disk-usage", cmd_filesystem_disk_usage,
> +			cmd_filesystem_disk_usage_usage, NULL, 0 },
> +

Same here, I'd suggest "du" or "usage".
As currently in the patch it's not shorthand-friendly, you basically propose
that people wishing a shorter invocation use it as "btrfs fi di" or "btrfs fi
disk", which seems awkward and not intuitive.

-- 
With respect,
Roman

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 198 bytes --]

  reply	other threads:[~2014-02-13 19:28 UTC|newest]

Thread overview: 34+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2014-02-13 19:18 [PATCH][BTRFS-PROGS][v4] Enhance btrfs fi df Goffredo Baroncelli
2014-02-13 19:19 ` [PATCH 1/8] Enhance the command btrfs filesystem df Goffredo Baroncelli
2014-02-13 19:19 ` [PATCH 2/8] Create the man page entry for the command btrfs fi df Goffredo Baroncelli
2014-02-13 19:19 ` [PATCH 3/8] Add helpers functions to handle the printing of data in tabular format Goffredo Baroncelli
2014-02-13 19:19 ` [PATCH 4/8] Allow use of get_device_info() Goffredo Baroncelli
2014-02-20 18:13   ` David Sterba
2014-02-13 19:19 ` [PATCH 5/8] Add command btrfs filesystem disk-usage Goffredo Baroncelli
2014-02-13 19:28   ` Roman Mamedov [this message]
2014-02-13 19:49     ` Goffredo Baroncelli
2014-02-13 20:22       ` Duncan
2014-02-13 21:00       ` Roman Mamedov
2014-02-14 17:57         ` Goffredo Baroncelli
2014-02-14 18:11           ` Roman Mamedov
2014-02-14 18:27             ` Goffredo Baroncelli
2014-02-14 18:34               ` Hugo Mills
2014-02-15 22:23                 ` Chris Murphy
2014-02-17 18:09                   ` Goffredo Baroncelli
2014-02-20 17:31                     ` David Sterba
2014-02-13 19:20 ` [PATCH 6/8] Create entry in man page for " Goffredo Baroncelli
2014-02-13 19:20 ` [PATCH 7/8] Add btrfs device disk-usage command Goffredo Baroncelli
2014-02-13 19:23   ` Roman Mamedov
2014-02-13 19:44     ` Goffredo Baroncelli
2014-02-13 19:20 ` [PATCH 8/8] Create a new entry in btrfs man page for btrfs device disk-usage Goffredo Baroncelli
2014-02-17 18:41 ` [PATCH][BTRFS-PROGS][v4] Enhance btrfs fi df David Sterba
2014-02-17 20:49   ` Goffredo Baroncelli
2014-02-20 18:08 ` David Sterba
2014-02-20 18:32   ` Josef Bacik
2014-02-20 19:20     ` Goffredo Baroncelli
2014-02-22  0:03     ` David Sterba
2014-02-20 19:18   ` Goffredo Baroncelli
  -- strict thread matches above, loose matches on Subject: below --
2013-03-10 12:17 [PATCH V3][BTRFS-PROGS] Enhance btrfs fi df with raid5/6 support Goffredo Baroncelli
2013-03-10 12:17 ` [PATCH 5/8] Add command btrfs filesystem disk-usage Goffredo Baroncelli
2013-02-23 13:46 [PATCH V2][BTRFS-PROGS] Enhance btrfs fi df with raid5/6 support Goffredo Baroncelli
2013-02-23 13:46 ` [PATCH 5/8] Add command btrfs filesystem disk-usage Goffredo Baroncelli
2013-02-18 21:04 [PATCH][BTRFS-PROGS] Enhance btrfs fi df with raid5/6 support Goffredo Baroncelli
2013-02-18 21:04 ` [PATCH 5/8] Add command btrfs filesystem disk-usage Goffredo Baroncelli
2012-11-02 10:15 [PATCH][BTRFS-PROGS] Enhance btrfs fi df Goffredo Baroncelli
2012-11-02 10:15 ` [PATCH 5/8] Add command btrfs filesystem disk-usage Goffredo Baroncelli

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20140214012810.26297146@natsu \
    --to=rm@romanrm.net \
    --cc=kreijack@inwind.it \
    --cc=kreijack@libero.it \
    --cc=linux-btrfs@vger.kernel.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.