linux-btrfs.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
From: Ilya Dryomov <idryomov@gmail.com>
To: Goffredo Baroncelli <kreijack@gmail.com>
Cc: linux-btrfs@vger.kernel.org, "Hugo Mills" <hugo@carfax.org.uk>,
	"Roman Mamedov" <rm@romanrm.ru>,
	"Sébastien Maury" <sebastien.maury@inserm.fr>,
	"Goffredo Baroncelli" <kreijack@inwind.it>
Subject: Re: [PATCH 1/2] Update btrfs filesystem df command
Date: Wed, 3 Oct 2012 23:34:00 +0300	[thread overview]
Message-ID: <20121003203400.GD2890@zambezi.lan> (raw)
In-Reply-To: <1349284952-6865-2-git-send-email-kreijack@inwind.com>

On Wed, Oct 03, 2012 at 07:22:31PM +0200, Goffredo Baroncelli wrote:
> From: Goffredo Baroncelli <kreijack@inwind.it>
> 
> The  command  btrfs  filesystem  df is used to query the
> status of the chunks, how many space on the disk(s) are used  by
> the  chunks,  how many space are available in the chunks, and an
> estimation of the free space of the filesystem.
> ---
>  cmds-filesystem.c |  284 ++++++++++++++++++++++++++++++++++++++++++++---------
>  1 file changed, 235 insertions(+), 49 deletions(-)
> 
> diff --git a/cmds-filesystem.c b/cmds-filesystem.c
> index b1457de..2701904 100644
> --- a/cmds-filesystem.c
> +++ b/cmds-filesystem.c
> @@ -22,6 +22,7 @@
>  #include <errno.h>
>  #include <uuid/uuid.h>
>  #include <ctype.h>
> +#include <sys/vfs.h>
>  
>  #include "kerncompat.h"
>  #include "ctree.h"
> @@ -39,25 +40,55 @@ static const char * const filesystem_cmd_group_usage[] = {
>  	NULL
>  };
>  
> -static const char * const cmd_df_usage[] = {
> -	"btrfs filesystem df <path>",
> -	"Show space usage information for a mount point",
> -	NULL
> -};
> +static u64 disk_size( char *path){
> +	struct statfs	sfs;
> +
> +	if( statfs(path, &sfs) < 0 )
> +		return 0;
> +	else
> +		return sfs.f_bsize * sfs.f_blocks;
> +
> +}
> +
> +static void print_string(char *s, int w)
> +{
> +	int	i;
> +
> +	printf("%s", s);
> +	for( i = strlen(s) ; i < w ; i++ ) 
> +		putchar(' ');
> +}
> +
> +#define DF_SHOW_SUMMARY 	(1<<1)
> +#define DF_SHOW_DETAIL		(1<<2)
> +#define DF_HUMAN_UNIT		(1<<3)
> +
> +static void pretty_sizes_r(u64 size, int w, int mode)
> +{
> +	if( mode & DF_HUMAN_UNIT ){
> +		char *s = pretty_sizes(size);
> +		printf("%*s", w, s);
> +		free(s);
> +	} else {
> +		printf("%*llu", w, size/1024);
> +
> +	}
> +}
>  
> -static int cmd_df(int argc, char **argv)
> +static int _cmd_disk_free(char *path, int mode)
>  {
>  	struct btrfs_ioctl_space_args *sargs;
>  	u64 count = 0, i;
>  	int ret;
>  	int fd;
> -	int e;
> -	char *path;
> -
> -	if (check_argc_exact(argc, 2))
> -		usage(cmd_df_usage);
> -
> -	path = argv[1];
> +	int e, width;
> +	u64  total_disk;		/* filesystem size == sum of
> +					   disks sizes */
> +	u64  total_chunks;		/* sum of chunks sizes on disk(s) */
> +	u64  total_used;		/* logical space used */
> +	u64  total_free;		/* logical space un-used */
> +	double K;
> +	
>  
>  	fd = open_file_or_dir(path);
>  	if (fd < 0) {
> @@ -103,56 +134,211 @@ static int cmd_df(int argc, char **argv)
>  		return ret;
>  	}
>  
> -	for (i = 0; i < sargs->total_spaces; i++) {
> -		char description[80];
> -		char *total_bytes;
> -		char *used_bytes;
> -		int written = 0;
> -		u64 flags = sargs->spaces[i].flags;
> +	total_disk = disk_size(path);
> +	e = errno;
> +	if( total_disk == 0 ){
> +		fprintf(stderr, "ERROR: couldn't get space info on '%s' - %s\n",
> +			path, strerror(e));
> +		close(fd);
> +		free(sargs);
> +		return 19;
> +	}
> +		
> +	total_chunks = total_used = total_free = 0;
>  
> -		memset(description, 0, 80);
> +	for (i = 0; i < sargs->total_spaces; i++) {
> +		int  ratio=1;
> +		u64  allocated;
>  
> -		if (flags & BTRFS_BLOCK_GROUP_DATA) {
> -			if (flags & BTRFS_BLOCK_GROUP_METADATA) {
> -				snprintf(description, 14, "%s",
> -					 "Data+Metadata");
> -				written += 13;
> -			} else {
> -				snprintf(description, 5, "%s", "Data");
> -				written += 4;
> -			}
> -		} else if (flags & BTRFS_BLOCK_GROUP_SYSTEM) {
> -			snprintf(description, 7, "%s", "System");
> -			written += 6;
> -		} else if (flags & BTRFS_BLOCK_GROUP_METADATA) {
> -			snprintf(description, 9, "%s", "Metadata");
> -			written += 8;
> -		}
> +		u64 flags = sargs->spaces[i].flags;
>  
>  		if (flags & BTRFS_BLOCK_GROUP_RAID0) {
> -			snprintf(description+written, 8, "%s", ", RAID0");
> -			written += 7;
> +			ratio=1;
>  		} else if (flags & BTRFS_BLOCK_GROUP_RAID1) {
> -			snprintf(description+written, 8, "%s", ", RAID1");
> -			written += 7;
> +			ratio=2;
>  		} else if (flags & BTRFS_BLOCK_GROUP_DUP) {
> -			snprintf(description+written, 6, "%s", ", DUP");
> -			written += 5;
> +			ratio=2;
>  		} else if (flags & BTRFS_BLOCK_GROUP_RAID10) {
> -			snprintf(description+written, 9, "%s", ", RAID10");
> -			written += 8;
> +			ratio=2;
> +		} else {
> +			ratio=1;
>  		}
>  
> -		total_bytes = pretty_sizes(sargs->spaces[i].total_bytes);
> -		used_bytes = pretty_sizes(sargs->spaces[i].used_bytes);
> -		printf("%s: total=%s, used=%s\n", description, total_bytes,
> -		       used_bytes);
> +		allocated = sargs->spaces[i].total_bytes * ratio;
> +
> +		total_chunks += allocated;
> +		total_used += sargs->spaces[i].used_bytes;
> +		total_free += (sargs->spaces[i].total_bytes - 
> +					sargs->spaces[i].used_bytes);
> +
> +	}
> +	K = ((double)total_used + (double)total_free) /
> +	                (double)total_chunks;
> +
> +	if( mode & DF_HUMAN_UNIT )
> +		width = 12;
> +	else
> +		width = 18;
> +
> +	printf("Path: %s\n", path);
> +	if( mode & DF_SHOW_SUMMARY ){
> +		printf("Summary:\n");
> +		printf("  Disk_size:\t\t");
> +		pretty_sizes_r(total_disk, width, mode);
> +		printf("\n  Disk_allocated:\t");
> +		pretty_sizes_r(total_chunks, width, mode);
> +		printf("\n  Disk_unallocated:\t"); 
> +		pretty_sizes_r(total_disk-total_chunks, width, mode);
> +		printf("\n  Logical_size:\t\t"); 
> +		pretty_sizes_r(total_used+total_free, width, mode);
> +		printf("\n  Used:\t\t\t"); 
> +		pretty_sizes_r(total_used, width, mode);
> +		printf("\n  Free_(Estimated):\t");
> +		pretty_sizes_r((u64)(K*total_disk-total_used), width, mode);
> +		printf("\t(Max: ");
> +		pretty_sizes_r(total_disk-total_chunks+total_free, 
> +				0, mode );
> +		printf(", Min: ");
> +		pretty_sizes_r((total_disk-total_chunks)/2+total_free, 
> +				0, mode );
> +		printf(")\n  Data_to_disk_ratio:\t%*.0f %%\n",
> +			width-2, K*100);
> +	}
> +
> +	if( ( mode & DF_SHOW_DETAIL ) && ( mode & DF_SHOW_SUMMARY ) )
> +		printf("\n");
> +
> +	if( mode & DF_SHOW_DETAIL ){
> +		/* Remember: the terminals have maximum 80 columns
> +		   do not believe to who says otherwise */
> +		printf("Details:\n");
> +		printf("  %-12s%-8s%*s%*s%*s\n",
> +			"Chunk_type", 
> +			"Mode",
> +			width, "Chunk_size", 
> +			width+1, "Logical_size", 
> +			width, "Used"
> +		);
> +
> +		for (i = 0; i < sargs->total_spaces; i++) {
> +			char *description="";
> +			int  ratio=1;
> +			char *r_mode;
> +			u64 allocated;
> +
> +			u64 flags = sargs->spaces[i].flags;
> +
> +			if (flags & BTRFS_BLOCK_GROUP_DATA) {
> +				if (flags & BTRFS_BLOCK_GROUP_METADATA){
> +					description = "Data+M.data";
> +				} else {
> +					description = "Data";
> +				}
> +			} else if (flags & BTRFS_BLOCK_GROUP_SYSTEM) {
> +				description = "System";
> +			} else if (flags & BTRFS_BLOCK_GROUP_METADATA) {
> +				description = "Metadata";
> +			}
> +
> +			if (flags & BTRFS_BLOCK_GROUP_RAID0) {
> +				r_mode = "RAID0";
> +				ratio=1;
> +			} else if (flags & BTRFS_BLOCK_GROUP_RAID1) {
> +				r_mode = "RAID1";
> +				ratio=2;
> +			} else if (flags & BTRFS_BLOCK_GROUP_DUP) {
> +				r_mode = "DUP";
> +				ratio=2;
> +			} else if (flags & BTRFS_BLOCK_GROUP_RAID10) {
> +				r_mode = "RAID10";
> +				ratio=2;
> +			} else {
> +				r_mode = "Single";
> +				ratio=1;
> +			}
> +
> +			allocated = sargs->spaces[i].total_bytes * ratio;
> +
> +			printf("  ");
> +			print_string(description,12);
> +			print_string(r_mode, 8);
> +			pretty_sizes_r(allocated, width, mode);
> +			pretty_sizes_r(sargs->spaces[i].total_bytes ,
> +				    width+1, mode);
> +	
> +			pretty_sizes_r(sargs->spaces[i].used_bytes, 
> +						width, mode);
> +			printf("\n");
> +
> +		}
>  	}
>  	free(sargs);
>  
>  	return 0;
>  }
>  
> +static const char * const cmd_disk_free_usage[] = {
> +	"btrfs filesystem df [-d|-s][-k] <path> [<path>..]",
> +	"Show space usage information for a mount point(s).",
> +	"",
> +	"-k\tSet KB (1024 bytes) as unit",
> +	"-s\tShow the summary section only",
> +	"-d\tShow the detail section only",
> +	NULL
> +};
> +
> +static int cmd_disk_free(int argc, char **argv)
> +{
> +
> +	int 	flags=DF_SHOW_SUMMARY|DF_SHOW_DETAIL|DF_HUMAN_UNIT;
> +	int	i, more_than_one=0;
> +
> +	optind = 1;
> +	while(1){
> +		char	c = getopt(argc, argv, "dsk");
> +		if(c<0)
> +			break;
> +		switch(c){
> +			case 'd':
> +				flags &= ~DF_SHOW_SUMMARY;
> +				break;
> +			case 's':
> +				flags &= ~DF_SHOW_DETAIL;
> +				break;
> +			case 'k':
> +				flags &= ~DF_HUMAN_UNIT;
> +				break;
> +			default:
> +				usage(cmd_disk_free_usage);
> +		}
> +	}
> +
> +	if( !(flags & (DF_SHOW_SUMMARY|DF_SHOW_DETAIL)) ){
> +		fprintf(stderr, "btrfs filesystem df: it is not possible to specify -s AND -d\n");

This doesn't look right at all.  You are adding two switches and
specifying both of them is an error?  A little too much for a command
whose job is to do some basic math and pretty-print the result.

How about displaying just the summary by default and then adding a
*single* switch (-v or whatever) for summary+details?

Thanks,

		Ilya

  reply	other threads:[~2012-10-03 20:34 UTC|newest]

Thread overview: 19+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2012-10-03 17:22 [PATCH][BTRFS-PROGS][V2] btrfs filesystem df Goffredo Baroncelli
2012-10-03 17:22 ` [PATCH 1/2] Update btrfs filesystem df command Goffredo Baroncelli
2012-10-03 20:34   ` Ilya Dryomov [this message]
2012-10-03 20:38     ` Hugo Mills
2012-10-03 20:43       ` Ilya Dryomov
2012-10-03 20:53       ` Goffredo Baroncelli
2012-10-03 17:22 ` [PATCH 2/2] Update help page Goffredo Baroncelli
2012-10-03 19:32 ` [PATCH][BTRFS-PROGS][V2] btrfs filesystem df David Sterba
2012-10-03 19:38   ` Goffredo Baroncelli
2012-10-04  7:15     ` David Sterba
  -- strict thread matches above, loose matches on Subject: below --
2012-10-13 19:14 [PATCH][BTRFS-PROGS][V6] " Goffredo Baroncelli
2012-10-13 19:14 ` [PATCH 1/2] Update btrfs filesystem df command Goffredo Baroncelli
2012-10-13 17:47 [PATCH][BTRFS-PROGS][V4] btrfs filesystem df Goffredo Baroncelli
2012-10-13 17:47 ` [PATCH 1/2] Update btrfs filesystem df command Goffredo Baroncelli
2012-10-04 17:27 [PATCH][BTRFS-PROGS][V3] btrfs filesystem df Goffredo Baroncelli
2012-10-04 17:27 ` [PATCH 1/2] Update btrfs filesystem df command Goffredo Baroncelli
2012-10-03 11:43 [PATCH][BTRFS-PROGS][V1] btrfs filesystem df Goffredo Baroncelli
2012-10-03 11:43 ` [PATCH 1/2] Update btrfs filesystem df command Goffredo Baroncelli
2012-10-03 15:02   ` Ilya Dryomov
2012-10-03 16:34     ` Goffredo Baroncelli
2012-10-03 17:20       ` Ilya Dryomov
2012-10-03 17:38         ` Goffredo Baroncelli
2012-10-03 17:09     ` 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=20121003203400.GD2890@zambezi.lan \
    --to=idryomov@gmail.com \
    --cc=hugo@carfax.org.uk \
    --cc=kreijack@gmail.com \
    --cc=kreijack@inwind.it \
    --cc=linux-btrfs@vger.kernel.org \
    --cc=rm@romanrm.ru \
    --cc=sebastien.maury@inserm.fr \
    /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 a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).