Re: [PATCH] btrfs: add new ioctl to determine size of compressed file

2011-12-19 Thread Liu Bo
On 12/19/2011 10:17 PM, David Sterba wrote:
> Go through all extents of a file in a given [start,end) range and sum
> for:
> * regular extent: ->block_len, size is already rounded up to blocks
> * inline extents: length rounded up to 512
> 
> The range is start inclusive / end exclusive. For the whole file pass
> 0 and (u64)-1.
> 
> The resulting value is number of occupied 512B sectors so this can
> be easily compared to stat.st_blocks to determine rough compression
> ratio of a file.
> 
> Based on implementation from Ulrich Hecht,
> http://comments.gmane.org/gmane.comp.file-systems.btrfs/6253
> 
> Signed-off-by: David Sterba 
> ---
>  fs/btrfs/ioctl.c |   77 
> ++
>  fs/btrfs/ioctl.h |   11 +++
>  2 files changed, 88 insertions(+), 0 deletions(-)
> 
> diff --git a/fs/btrfs/ioctl.c b/fs/btrfs/ioctl.c
> index c04f02c..82c3810 100644
> --- a/fs/btrfs/ioctl.c
> +++ b/fs/btrfs/ioctl.c
> @@ -2972,6 +2972,81 @@ static int build_ino_list(u64 inum, u64 offset, u64 
> root, void *ctx)
>   return 0;
>  }
>  
> +/*
> + * Returns the compressed size of an inode in 512 byte blocks.
> + * Count the on-disk space used by extents starting in range [start, end),
> + * inline data are rounded up to sector, ie. 512.
> + *
> + * The range is start inclusive and end exclusive so it can be used to
> + * determine compressed size of a given extent by its start and start of the
> + * next extent easily, without counting length.
> + * Whole file is specified as start = 0, end = (u64)-1
> + */
> +static long btrfs_ioctl_compr_size(struct file *file, void __user *argp)
> +{
> + struct inode *inode = fdentry(file)->d_inode;
> + struct btrfs_ioctl_compr_size_args compr_args;
> + u64 len;
> + u64 compressed_size = 0;
> + u64 offset = 0;
> +
> + if (S_ISDIR(inode->i_mode))
> + return -EISDIR;
> +
> + if (copy_from_user(&compr_args, argp,
> + sizeof(struct btrfs_ioctl_compr_size_args)))
> + return -EFAULT;
> +
> + if (compr_args.start > compr_args.end)
> + return -EINVAL;
> +
> + mutex_lock(&inode->i_mutex);
> +
> + offset = compr_args.start;
> + if (inode->i_size > compr_args.end)
> + len = compr_args.end;
> + else
> + len = inode->i_size;
> +
> + /*
> +  * do any pending delalloc/csum calc on inode, one way or
> +  * another, and lock file content
> +  */
> + btrfs_wait_ordered_range(inode, compr_args.start, len);
> +


missing a lock_extent() ?
and we may adjust i_mutex and [un]lock_extent.

thanks,
liubo

> + while (offset < len) {
> + struct extent_map *em;
> +
> + em = btrfs_get_extent(inode, NULL, 0, offset, 1, 0);
> + if (IS_ERR_OR_NULL(em))
> + goto error;
> + if (em->block_len != (u64)-1)
> + compressed_size += em->block_len;
> + else if (em->block_start == EXTENT_MAP_INLINE) {
> + compressed_size += ALIGN(em->len, 512);
> + }
> + offset += em->len;
> + free_extent_map(em);
> + }
> + mutex_unlock(&inode->i_mutex);
> +
> + unlock_extent(&BTRFS_I(inode)->io_tree, compr_args.start, len, 
> GFP_NOFS);
> +
> + compr_args.size = compressed_size >> 9;
> +
> + if (copy_to_user(argp, &compr_args, sizeof(struct
> + btrfs_ioctl_compr_size_args)))
> + return -EFAULT;
> +
> + return 0;
> +
> +error:
> + mutex_unlock(&inode->i_mutex);
> + unlock_extent(&BTRFS_I(inode)->io_tree, compr_args.start, len, 
> GFP_NOFS);
> +
> + return -EIO;
> +}
> +
>  static long btrfs_ioctl_logical_to_ino(struct btrfs_root *root,
>   void __user *arg)
>  {
> @@ -3110,6 +3185,8 @@ long btrfs_ioctl(struct file *file, unsigned int
>   return btrfs_ioctl_scrub_cancel(root, argp);
>   case BTRFS_IOC_SCRUB_PROGRESS:
>   return btrfs_ioctl_scrub_progress(root, argp);
> + case BTRFS_IOC_COMPR_SIZE:
> + return btrfs_ioctl_compr_size(file, argp);
>   }
>  
>   return -ENOTTY;
> diff --git a/fs/btrfs/ioctl.h b/fs/btrfs/ioctl.h
> index 252ae99..bce761c 100644
> --- a/fs/btrfs/ioctl.h
> +++ b/fs/btrfs/ioctl.h
> @@ -217,6 +217,15 @@ struct btrfs_ioctl_logical_ino_args {
>   __u64   inodes;
>  };
>  
> +struct btrfs_ioctl_compr_size_args {
> + /* Range start, inclusive */
> + __u64   start;  /* in */
> + /* Range end, exclusive */
> + __u64   end;/* in */
> + __u64   size;   /* out */
> + __u64   reserved[2];
> +};
> +
>  #define BTRFS_IOC_SNAP_CREATE _IOW(BTRFS_IOCTL_MAGIC, 1, \
>  struct btrfs_ioctl_vol_args)
>  #define BTRFS_IOC_DE

Re: Error: btrfs bad tree block

2011-12-19 Thread Mathieu Chouquet-Stringer
On Mon, Dec 19, 2011 at 01:33:05PM +0100, Mathieu Chouquet-Stringer wrote:
> Any idea what I could try next?

Or fsck I could use? ;-)
-- 
Mathieu Chouquet-Stringer math...@csetco.com
The sun itself sees not till heaven clears.
 -- William Shakespeare --
--
To unsubscribe from this list: send the line "unsubscribe linux-btrfs" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: A sample tool how to use the new ioctl

2011-12-19 Thread David Sterba
On Mon, Dec 19, 2011 at 09:47:06AM -0500, Chris Mason wrote:
> On Mon, Dec 19, 2011 at 03:25:39PM +0100, David Sterba wrote:
> > This is a standalone tool I've used to exercise the ioctl, simply pass
> Could you please add this to btrfs filesystem stat 

Here it is, but I haven't really thought about the userspace interface and
calling it 'stat' just for reading compressed size does not seem right (and I
have renamed to 'csize' for now).

I will extend the ioctl to return the uncompressed size as well, it is provided
by the extent anyway. The original implementation returned just one u64 for the
whole file, I did the range-aware version because the lock_extent blocked for a
long time when the file was being modified and it could be avoided. However I
missed the options to utilize the information provided by the extents,
so this is not a final version.

From: David Sterba 

Signed-off-by: David Sterba 
---
 btrfs.c  |9 -
 btrfs_cmds.c |   53 +
 btrfs_cmds.h |1 +
 ioctl.h  |   11 +++
 4 files changed, 73 insertions(+), 1 deletions(-)

diff --git a/btrfs.c b/btrfs.c
index 1def354..5ce207a 100644
--- a/btrfs.c
+++ b/btrfs.c
@@ -128,7 +128,14 @@ static struct Command commands[] = {
  "filesystem label", " []\n"
  "With one argument, get the label of filesystem on .\n"
  "If  is passed, set the filesystem label to .\n"
- "The filesystem must be unmounted.\n"
+ "The filesystem must be unmounted."
+   },
+   { do_compr_size, -1,
+ "filesystem csize", "[-s start] [-e end] file\n"
+ "Read compressed size of extents in the range [start,end)\n"
+ "-s start  range start inclusive\n"
+ "-e endrange end exclusive\n",
+ NULL
},
{ do_scrub_start, -1,
  "scrub start", "[-Bdqr] |\n"
diff --git a/btrfs_cmds.c b/btrfs_cmds.c
index b59e9cb..4c8bf5c 100644
--- a/btrfs_cmds.c
+++ b/btrfs_cmds.c
@@ -1305,3 +1305,56 @@ out:
free(inodes);
return ret;
 }
+
+int do_compr_size(int argc, char **argv)
+{
+   int ret;
+   int fd;
+   struct btrfs_ioctl_compr_size_args args;
+
+   args.start = 0;
+   args.end = (u64)-1;
+   optind = 1;
+   while (1) {
+   int c = getopt(argc, argv, "s:e:");
+   if (c < 0)
+   break;
+   switch (c) {
+   case 's':
+   args.start = parse_size(optarg);
+   break;
+   case 'e':
+   args.end = parse_size(optarg);
+   break;
+   default:
+   fprintf(stderr, "ERROR: Invalid arguments for csize\n");
+   return 1;
+   }
+   }
+
+   if (args.start > args.end) {
+   fprintf(stderr, "ERROR: Invalid range for csize\n");
+   return 1;
+   }
+
+   if (argc - optind == 0) {
+   fprintf(stderr, "ERROR: Invalid arguments for csize\n");
+   return 1;
+   }
+   argc -= optind;
+
+   fd = open_file_or_dir(argv[optind]);
+   if (fd < 0) {
+   fprintf(stderr, "ERROR: can't access '%s'\n", argv[optind]);
+   return 1;
+   }
+
+   ret = ioctl(fd, BTRFS_IOC_COMPR_SIZE, &args);
+   if (ret < 0) {
+   fprintf(stderr, "ERROR: ioctl returned %d, errno %d %s\n", ret, 
errno, strerror(errno));
+   return errno;
+   }
+
+   printf("Compressed size: %llu\n", args.size << 9);
+   return 0;
+}
diff --git a/btrfs_cmds.h b/btrfs_cmds.h
index 81182b1..d171214 100644
--- a/btrfs_cmds.h
+++ b/btrfs_cmds.h
@@ -42,3 +42,4 @@ int open_file_or_dir(const char *fname);
 int do_ino_to_path(int nargs, char **argv);
 int do_logical_to_ino(int nargs, char **argv);
 char *path_for_root(int fd, u64 root);
+int do_compr_size(int argc, char **argv);
diff --git a/ioctl.h b/ioctl.h
index 1ae7537..792ffc0 100644
--- a/ioctl.h
+++ b/ioctl.h
@@ -224,6 +224,15 @@ struct btrfs_ioctl_logical_ino_args {
__u64   inodes;
 };
 
+struct btrfs_ioctl_compr_size_args {
+   /* Range start, inclusive */
+   __u64   start;  /* in */
+   /* Range end, exclusive */
+   __u64   end;/* in */
+   __u64   size;   /* out */
+   __u64   reserved[2];
+};
+
 /* BTRFS_IOC_SNAP_CREATE is no longer used by the btrfs command */
 #define BTRFS_IOC_SNAP_CREATE _IOW(BTRFS_IOCTL_MAGIC, 1, \
   struct btrfs_ioctl_vol_args)
@@ -277,5 +286,7 @@ struct btrfs_ioctl_logical_ino_args {
struct btrfs_ioctl_ino_path_args)
 #define BTRFS_IOC_LOGICAL_INO _IOWR(BTRFS_IOCTL_MAGIC, 36, \
struc

Re: A sample tool how to use the new ioctl

2011-12-19 Thread Chris Mason
On Mon, Dec 19, 2011 at 03:25:39PM +0100, David Sterba wrote:
> This is a standalone tool I've used to exercise the ioctl, simply pass
> the name of a file and see the result. The numbers are a rough
> estimate. It also takes the range arguments, but the ratio will be bogus
> due to comparison to whole file (st_blocks), an exact extent length
> from fiemap/filefrag is be the correct one.

Thanks Dave.

Could you please add this to btrfs filesystem stat 

-chris
--
To unsubscribe from this list: send the line "unsubscribe linux-btrfs" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


btrfs crashing 3.2.0-030200rc2-generic

2011-12-19 Thread Hadmut Danisch
Hi,

just in case anybody wants to know: btrfs just crashed my kernel.

regards



Dec 19 15:13:53 sodom kernel: [19781.993189] INFO: task
udisks-daemon:2987 blocked for more than 120 seconds.
Dec 19 15:13:53 sodom kernel: [19781.993192] "echo 0 >
/proc/sys/kernel/hung_task_timeout_secs" disables this message.
Dec 19 15:13:53 sodom kernel: [19781.993194] udisks-daemon   D
8803bfe51ab0 0  2987   2984 0x
Dec 19 15:13:53 sodom kernel: [19781.993197]  8803bfed7b28
0082  3ee8e83f
Dec 19 15:13:53 sodom kernel: [19781.993200]  00013640
8803bfed7fd8 8803bfed6010 00013640
Dec 19 15:13:53 sodom kernel: [19781.993203]  8803bfed7fd8
00013640 81c0d020 8803bfe516f0
Dec 19 15:13:53 sodom kernel: [19781.993206] Call Trace:
Dec 19 15:13:53 sodom kernel: [19781.993211]  [] ?
get_disk+0x56/0xc0
Dec 19 15:13:53 sodom kernel: [19781.993214]  []
schedule+0x3f/0x60
Dec 19 15:13:53 sodom kernel: [19781.993217]  []
__mutex_lock_slowpath+0xdf/0x160
Dec 19 15:13:53 sodom kernel: [19781.993219]  []
mutex_lock+0x2b/0x50
Dec 19 15:13:53 sodom kernel: [19781.993222]  []
__blkdev_get+0x73/0x430
Dec 19 15:13:53 sodom kernel: [19781.993225]  []
blkdev_get+0x5c/0x210
Dec 19 15:13:53 sodom kernel: [19781.993227]  [] ?
_raw_spin_lock+0xe/0x20
Dec 19 15:13:53 sodom kernel: [19781.993229]  []
blkdev_open+0x62/0x80
Dec 19 15:13:53 sodom kernel: [19781.993232]  []
__dentry_open+0x243/0x350
Dec 19 15:13:53 sodom kernel: [19781.993235]  [] ?
do_lookup+0x4b/0x390
Dec 19 15:13:53 sodom kernel: [19781.993237]  [] ?
blkdev_get+0x210/0x210
Dec 19 15:13:53 sodom kernel: [19781.993239]  []
nameidata_to_filp+0x71/0x80
Dec 19 15:13:53 sodom kernel: [19781.993241]  []
do_last+0x3d8/0x800
Dec 19 15:13:53 sodom kernel: [19781.993243]  []
path_openat+0xd5/0x3f0
Dec 19 15:13:53 sodom kernel: [19781.993259]  [] ?
scsi_device_put+0x44/0x60
Dec 19 15:13:53 sodom kernel: [19781.993261]  []
do_filp_open+0x49/0xa0
Dec 19 15:13:53 sodom kernel: [19781.993264]  [] ?
strncpy_from_user+0x4a/0x90
Dec 19 15:13:53 sodom kernel: [19781.993266]  [] ?
_raw_spin_lock+0xe/0x20
Dec 19 15:13:53 sodom kernel: [19781.993269]  [] ?
alloc_fd+0x10a/0x150
Dec 19 15:13:53 sodom kernel: [19781.993271]  []
do_sys_open+0x107/0x1e0
Dec 19 15:13:53 sodom kernel: [19781.993273]  []
sys_open+0x20/0x30
Dec 19 15:13:53 sodom kernel: [19781.993276]  []
system_call_fastpath+0x16/0x1b
Dec 19 15:13:53 sodom kernel: [19781.993295] INFO: task blkid:12144
blocked for more than 120 seconds.
Dec 19 15:13:53 sodom kernel: [19781.993297] "echo 0 >
/proc/sys/kernel/hung_task_timeout_secs" disables this message.
Dec 19 15:13:53 sodom kernel: [19781.993298] blkid   D
88038b4fc890 0 12144  12075 0x0004
Dec 19 15:13:53 sodom kernel: [19781.993301]  8802ab9cbb28
0086 e400 
Dec 19 15:13:53 sodom kernel: [19781.993303]  00013640
8802ab9cbfd8 8802ab9ca010 00013640
Dec 19 15:13:53 sodom kernel: [19781.993306]  8802ab9cbfd8
00013640 8804055a16f0 88038b4fc4d0
Dec 19 15:13:53 sodom kernel: [19781.993308] Call Trace:
Dec 19 15:13:53 sodom kernel: [19781.993310]  []
schedule+0x3f/0x60
Dec 19 15:13:53 sodom kernel: [19781.993312]  []
__mutex_lock_slowpath+0xdf/0x160
Dec 19 15:13:53 sodom kernel: [19781.993315]  []
mutex_lock+0x2b/0x50
Dec 19 15:13:53 sodom kernel: [19781.993317]  []
__blkdev_get+0x73/0x430
Dec 19 15:13:53 sodom kernel: [19781.993319]  []
blkdev_get+0x5c/0x210
Dec 19 15:13:53 sodom kernel: [19781.993322]  [] ?
_raw_spin_lock+0xe/0x20
Dec 19 15:13:53 sodom kernel: [19781.993324]  []
blkdev_open+0x62/0x80
Dec 19 15:13:53 sodom kernel: [19781.993326]  []
__dentry_open+0x243/0x350
Dec 19 15:13:53 sodom kernel: [19781.993328]  [] ?
do_lookup+0x4b/0x390
Dec 19 15:13:53 sodom kernel: [19781.993330]  [] ?
blkdev_get+0x210/0x210
Dec 19 15:13:53 sodom kernel: [19781.993332]  []
nameidata_to_filp+0x71/0x80
Dec 19 15:13:53 sodom kernel: [19781.993334]  []
do_last+0x3d8/0x800
Dec 19 15:13:53 sodom kernel: [19781.993336]  []
path_openat+0xd5/0x3f0
Dec 19 15:13:53 sodom kernel: [19781.993338]  []
do_filp_open+0x49/0xa0
Dec 19 15:13:53 sodom kernel: [19781.993340]  [] ?
strncpy_from_user+0x4a/0x90
Dec 19 15:13:53 sodom kernel: [19781.993342]  [] ?
_raw_spin_lock+0xe/0x20
Dec 19 15:13:53 sodom kernel: [19781.993344]  [] ?
alloc_fd+0x10a/0x150
Dec 19 15:13:53 sodom kernel: [19781.993346]  []
do_sys_open+0x107/0x1e0
Dec 19 15:13:53 sodom kernel: [19781.993348]  []
sys_open+0x20/0x30
Dec 19 15:13:53 sodom kernel: [19781.993350]  []
system_call_fastpath+0x16/0x1b
Dec 19 15:14:15 sodom kernel: [19803.828253] [ cut here
]
Dec 19 15:14:15 sodom kernel: [19803.830588] kernel BUG at
/home/apw/COD/linux/fs/btrfs/transaction.c:1329!
Dec 19 15:14:15 sodom kernel: [19803.831738] invalid opcode:  [#1] SMP
Dec 19 15:14:15 sodom kernel: [19803.832877] CPU 0
Dec 19 15:14:15 sodom kernel: [19803.832882] Mod

A sample tool how to use the new ioctl

2011-12-19 Thread David Sterba
This is a standalone tool I've used to exercise the ioctl, simply pass
the name of a file and see the result. The numbers are a rough
estimate. It also takes the range arguments, but the ratio will be bogus
due to comparison to whole file (st_blocks), an exact extent length
from fiemap/filefrag is be the correct one.


david

/*
 * 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 
#include 
#include 
#include 
#include 
#include 
#include 
#include 

typedef uint64_t __u64;
typedef uint64_t u64;

#ifndef BTRFS_IOCTL_MAGIC
#define BTRFS_IOCTL_MAGIC 0x94
#endif

#ifndef BTRFS_IOC_COMPR_SIZE
#define BTRFS_IOC_COMPR_SIZE _IOR(BTRFS_IOCTL_MAGIC, 51, \
		struct __local__btrfs_ioctl_compr_size_args)
#endif

struct __local__btrfs_ioctl_compr_size_args {
	/* Range start, inclusive */
	__u64   start;  /* in */
	/* Range end, exclusive */
	__u64   end;/* in */
	__u64   size;   /* out */
	__u64   reserved[2];
};

static u64 parse_size(char *s)
{
	int len = strlen(s);
	char c;
	u64 mult = 1;

	if (!isdigit(s[len - 1])) {
		c = tolower(s[len - 1]);
		switch (c) {
			case 'e':
			case 'E':
mult *= 1024;
			case 't':
			case 'T':
mult *= 1024;
			case 'g':
			case 'G':
mult *= 1024;
			case 'm':
			case 'M':
mult *= 1024;
			case 'k':
			case 'K':
mult *= 1024;
			case 'b':
			case 'B':
break;
			default:
fprintf(stderr, "Unknown size descriptor %c\n", c);
exit(1);
		}
		s[len - 1] = '\0';
	}
	return atoll(s) * mult;
}

static int open_file_or_dir(const char *fname)
{
	int ret;
	struct stat st;
	DIR *dirstream;
	int fd;

	ret = stat(fname, &st);
	if (ret < 0) {
		perror("stat");
		exit(1);
	}
	if (S_ISDIR(st.st_mode)) {
		dirstream = opendir(fname);
		if (!dirstream) {
			perror("opendir");
			exit(1);
		}
		fd = dirfd(dirstream);
	} else {
		fd = open(fname, O_RDONLY);
	}
	if (fd < 0) {
		perror("open");
		exit(1);
	}
	return fd;
}
static char buf[64];
static const char* end_or_eof(u64 end)
{
	if (end == (u64)-1)
		return "EOF";
	snprintf(buf, 64, "%llu", (unsigned long long)end);
	return buf;
}

int main(int argc, char **argv)
{
	int fd;
	int ret;
	u64 cblocks;
	unsigned long sblocks;
	struct stat st;
	struct __local__btrfs_ioctl_compr_size_args args;

	if (argc < 2) {
		printf("Usage: btrfs-compr-size  [start [end] ]\n");
		exit(1);
	}

	fd = open_file_or_dir(argv[1]);
	if (fd == -1) {
		perror("open");
		exit(1);
	}

	if (argc >= 3)
		args.start = parse_size(argv[2]);
	else
		args.start = 0;

	if (argc >= 4)
		args.end = parse_size(argv[3]);
	else
		args.end = (u64)-1;

	ret = ioctl(fd, BTRFS_IOC_COMPR_SIZE, &args);
	if (ret < 0) {
		perror("ioctl");
		exit(1);
	}
	fstat(fd, &st);
	cblocks=args.size;
	sblocks=st.st_blocks;
	printf("Compressed size of %s [%llu,%s)\n", argv[1],
			(unsigned long long)args.start,
			end_or_eof(args.end));
	printf(" compr size/512:  % 11lu\n", cblocks);
	printf(" stat blocks/512: % 11lu\n", sblocks);
	if (sblocks)
		printf(" compr/stat*100:  % 14.2f%%\n", (((float)cblocks) / sblocks) * 100);
	else
		printf(" compr/stat*100:  % 14.2f%%\n", (float)0);
	return 0;
}


[PATCH] btrfs: add new ioctl to determine size of compressed file

2011-12-19 Thread David Sterba
Go through all extents of a file in a given [start,end) range and sum
for:
* regular extent: ->block_len, size is already rounded up to blocks
* inline extents: length rounded up to 512

The range is start inclusive / end exclusive. For the whole file pass
0 and (u64)-1.

The resulting value is number of occupied 512B sectors so this can
be easily compared to stat.st_blocks to determine rough compression
ratio of a file.

Based on implementation from Ulrich Hecht,
http://comments.gmane.org/gmane.comp.file-systems.btrfs/6253

Signed-off-by: David Sterba 
---
 fs/btrfs/ioctl.c |   77 ++
 fs/btrfs/ioctl.h |   11 +++
 2 files changed, 88 insertions(+), 0 deletions(-)

diff --git a/fs/btrfs/ioctl.c b/fs/btrfs/ioctl.c
index c04f02c..82c3810 100644
--- a/fs/btrfs/ioctl.c
+++ b/fs/btrfs/ioctl.c
@@ -2972,6 +2972,81 @@ static int build_ino_list(u64 inum, u64 offset, u64 
root, void *ctx)
return 0;
 }
 
+/*
+ * Returns the compressed size of an inode in 512 byte blocks.
+ * Count the on-disk space used by extents starting in range [start, end),
+ * inline data are rounded up to sector, ie. 512.
+ *
+ * The range is start inclusive and end exclusive so it can be used to
+ * determine compressed size of a given extent by its start and start of the
+ * next extent easily, without counting length.
+ * Whole file is specified as start = 0, end = (u64)-1
+ */
+static long btrfs_ioctl_compr_size(struct file *file, void __user *argp)
+{
+   struct inode *inode = fdentry(file)->d_inode;
+   struct btrfs_ioctl_compr_size_args compr_args;
+   u64 len;
+   u64 compressed_size = 0;
+   u64 offset = 0;
+
+   if (S_ISDIR(inode->i_mode))
+   return -EISDIR;
+
+   if (copy_from_user(&compr_args, argp,
+   sizeof(struct btrfs_ioctl_compr_size_args)))
+   return -EFAULT;
+
+   if (compr_args.start > compr_args.end)
+   return -EINVAL;
+
+   mutex_lock(&inode->i_mutex);
+
+   offset = compr_args.start;
+   if (inode->i_size > compr_args.end)
+   len = compr_args.end;
+   else
+   len = inode->i_size;
+
+   /*
+* do any pending delalloc/csum calc on inode, one way or
+* another, and lock file content
+*/
+   btrfs_wait_ordered_range(inode, compr_args.start, len);
+
+   while (offset < len) {
+   struct extent_map *em;
+
+   em = btrfs_get_extent(inode, NULL, 0, offset, 1, 0);
+   if (IS_ERR_OR_NULL(em))
+   goto error;
+   if (em->block_len != (u64)-1)
+   compressed_size += em->block_len;
+   else if (em->block_start == EXTENT_MAP_INLINE) {
+   compressed_size += ALIGN(em->len, 512);
+   }
+   offset += em->len;
+   free_extent_map(em);
+   }
+   mutex_unlock(&inode->i_mutex);
+
+   unlock_extent(&BTRFS_I(inode)->io_tree, compr_args.start, len, 
GFP_NOFS);
+
+   compr_args.size = compressed_size >> 9;
+
+   if (copy_to_user(argp, &compr_args, sizeof(struct
+   btrfs_ioctl_compr_size_args)))
+   return -EFAULT;
+
+   return 0;
+
+error:
+   mutex_unlock(&inode->i_mutex);
+   unlock_extent(&BTRFS_I(inode)->io_tree, compr_args.start, len, 
GFP_NOFS);
+
+   return -EIO;
+}
+
 static long btrfs_ioctl_logical_to_ino(struct btrfs_root *root,
void __user *arg)
 {
@@ -3110,6 +3185,8 @@ long btrfs_ioctl(struct file *file, unsigned int
return btrfs_ioctl_scrub_cancel(root, argp);
case BTRFS_IOC_SCRUB_PROGRESS:
return btrfs_ioctl_scrub_progress(root, argp);
+   case BTRFS_IOC_COMPR_SIZE:
+   return btrfs_ioctl_compr_size(file, argp);
}
 
return -ENOTTY;
diff --git a/fs/btrfs/ioctl.h b/fs/btrfs/ioctl.h
index 252ae99..bce761c 100644
--- a/fs/btrfs/ioctl.h
+++ b/fs/btrfs/ioctl.h
@@ -217,6 +217,15 @@ struct btrfs_ioctl_logical_ino_args {
__u64   inodes;
 };
 
+struct btrfs_ioctl_compr_size_args {
+   /* Range start, inclusive */
+   __u64   start;  /* in */
+   /* Range end, exclusive */
+   __u64   end;/* in */
+   __u64   size;   /* out */
+   __u64   reserved[2];
+};
+
 #define BTRFS_IOC_SNAP_CREATE _IOW(BTRFS_IOCTL_MAGIC, 1, \
   struct btrfs_ioctl_vol_args)
 #define BTRFS_IOC_DEFRAG _IOW(BTRFS_IOCTL_MAGIC, 2, \
@@ -276,5 +285,7 @@ struct btrfs_ioctl_logical_ino_args {
struct btrfs_ioctl_ino_path_args)
 #define BTRFS_IOC_LOGICAL_INO _IOWR(BTRFS_IOCTL_MAGIC, 36, \
struct btrfs_ioctl_ino

Error: btrfs bad tree block

2011-12-19 Thread Mathieu Chouquet-Stringer
Hello,

It seems BTRFS finally gave up on me! :-)  I've been using as my main FS
for quite a while and this time I'm not able to fix this issue.

I've tried mounting with -o clear_cache, zeroing the log and changing
super but I'm still getting this over and over:

btrfs bad tree block start 0 204055724032

This is running 3.2.0-rc6-5-ga36bfdd

I've tried btrfsck but it segfaults haha...

I didn't do anything special before that except I had a bunch of
subvolumes and I deleted them.

Any idea what I could try next?

Thanks in advance,
-- 
Mathieu Chouquet-Stringer math...@csetco.com
The sun itself sees not till heaven clears.
 -- William Shakespeare --
--
To unsubscribe from this list: send the line "unsubscribe linux-btrfs" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html