public inbox for linux-btrfs@vger.kernel.org
 help / color / mirror / Atom feed
* measuring btrfs compression
@ 2009-04-06  6:32 mp3geek
  2009-04-07  3:18 ` Chris Mason
  0 siblings, 1 reply; 4+ messages in thread
From: mp3geek @ 2009-04-06  6:32 UTC (permalink / raw)
  To: linux-btrfs

Just wondering how do I measure the compression used in btrfs?

^ permalink raw reply	[flat|nested] 4+ messages in thread

* Re: measuring btrfs compression
  2009-04-06  6:32 measuring btrfs compression mp3geek
@ 2009-04-07  3:18 ` Chris Mason
  2009-04-19  3:56   ` [REVIEW] Btrfs: Introduce ioctl for compressed size of file Chris Ball
  0 siblings, 1 reply; 4+ messages in thread
From: Chris Mason @ 2009-04-07  3:18 UTC (permalink / raw)
  To: mp3geek; +Cc: linux-btrfs

On Mon, 2009-04-06 at 18:32 +1200, mp3geek wrote:
> Just wondering how do I measure the compression used in btrfs?

I'm afraid the best way right now is to compare the storage reported in
the FS by df with the sizes of the files reported by du.

We need to add an ioctl that reports on the actual size of the
compressed file.

-chris


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


^ permalink raw reply	[flat|nested] 4+ messages in thread

* [REVIEW] Btrfs: Introduce ioctl for compressed size of file
  2009-04-07  3:18 ` Chris Mason
@ 2009-04-19  3:56   ` Chris Ball
  2009-04-23 19:20     ` Chris Mason
  0 siblings, 1 reply; 4+ messages in thread
From: Chris Ball @ 2009-04-19  3:56 UTC (permalink / raw)
  To: Chris Mason; +Cc: mp3geek, linux-btrfs

Hi,

   > We need to add an ioctl that reports on the actual size of the
   > compressed file.

Here's an attempt at that ioctl, please review.  The search code is
based on the clone ioctl.  Some specific questions:

* Is the first while() loop necessary?
* Are the semantics of returning -EINVAL when called on an FS with
  compression disabled desirable?

Example usage:

# ls -la english.txt
-rw-r--r-- 1 root root 316601 2009-04-18 22:53 english.txt

# python -c 'import fcntl; file = open("english.txt"); \
  print fcntl.ioctl(file, 0x940f);'
151552

# gzip -1 english.txt; ls -la english.txt.gz
-rw-r--r-- 1 root root 152737 2009-04-18 22:53 english.txt.gz

Thanks,

- Chris.

---
 fs/btrfs/ioctl.c |  113 ++++++++++++++++++++++++++++++++++++++++++++++++++++++
 fs/btrfs/ioctl.h |    1 +
 2 files changed, 114 insertions(+), 0 deletions(-)

diff --git a/fs/btrfs/ioctl.c b/fs/btrfs/ioctl.c
index bca729f..ae50c3b 100644
--- a/fs/btrfs/ioctl.c
+++ b/fs/btrfs/ioctl.c
@@ -1013,6 +1013,117 @@ out_drop_write:
 	return ret;
 }
 
+static unsigned long btrfs_ioctl_compsize(struct file *file)
+{
+	/* This ioctl returns the compressed size of an inode on disk
+	 * by counting the on-disk space used by all of its extents.
+	 */
+	struct inode *inode = fdentry(file)->d_inode;
+	struct btrfs_root *root = BTRFS_I(inode)->root;
+	struct btrfs_path *path;
+	struct extent_buffer *leaf;
+	struct btrfs_key key;
+	u32 nritems;
+	int slot;
+	u64 olen = inode->i_size;
+	u64 len = olen;
+	unsigned long ret;
+	unsigned long compressed_size = 0;
+
+	if (!btrfs_test_opt(root, COMPRESS))
+		return -EINVAL;
+
+	if (S_ISDIR(inode->i_mode))
+		return -EISDIR;
+
+	path = btrfs_alloc_path();
+	if (!path)
+		return -ENOMEM;
+
+	path->reada = 2;
+	mutex_lock(&inode->i_mutex);
+
+	/* do any pending delalloc/csum calc on inode, one way or
+	   another, and lock file content */
+	while (1) {
+		struct btrfs_ordered_extent *ordered;
+		lock_extent(&BTRFS_I(inode)->io_tree, 0, len, GFP_NOFS);
+		ordered = btrfs_lookup_first_ordered_extent(inode, len);
+		if (BTRFS_I(inode)->delalloc_bytes == 0 && !ordered)
+			break;
+		unlock_extent(&BTRFS_I(inode)->io_tree, 0, len, GFP_NOFS);
+		if (ordered)
+			btrfs_put_ordered_extent(ordered);
+		btrfs_wait_ordered_range(inode, 0, len);
+	}
+
+	/* search for the inode */
+	key.objectid = inode->i_ino;
+	key.type = BTRFS_EXTENT_DATA_KEY;
+	key.offset = 0;
+
+	while (1) {
+		/* note the key will change type as we walk through the tree */
+		ret = btrfs_search_slot(NULL, root, &key, path, 0, 0);
+		if (ret < 0)
+			goto out;
+
+		nritems = btrfs_header_nritems(path->nodes[0]);
+		if (path->slots[0] >= nritems) {
+			ret = btrfs_next_leaf(root, path);
+			if (ret < 0)
+				goto out;
+			if (ret > 0)
+				break;
+			nritems = btrfs_header_nritems(path->nodes[0]);
+		}
+		leaf = path->nodes[0];
+		slot = path->slots[0];
+
+		btrfs_item_key_to_cpu(leaf, &key, slot);
+		if (btrfs_key_type(&key) > BTRFS_EXTENT_DATA_KEY ||
+		    key.objectid != inode->i_ino)
+			break;
+
+		if (btrfs_key_type(&key) == BTRFS_EXTENT_DATA_KEY) {
+			struct btrfs_file_extent_item *extent;
+			int type;
+			u64 datal = 0;
+
+			extent = btrfs_item_ptr(leaf, slot,
+						struct btrfs_file_extent_item);
+			type = btrfs_file_extent_type(leaf, extent);
+			if (type == BTRFS_FILE_EXTENT_REG) {
+				datal = btrfs_file_extent_num_bytes(leaf,
+								    extent);
+				compressed_size +=
+				  btrfs_file_extent_disk_num_bytes(leaf,
+								   extent);
+			} else if (type == BTRFS_FILE_EXTENT_INLINE) {
+				datal = btrfs_file_extent_ram_bytes(leaf,
+								    extent);
+				compressed_size +=
+				  btrfs_file_extent_inline_item_len(leaf,
+					      btrfs_item_nr(leaf, slot));
+			}
+			btrfs_release_path(root, path);
+		}
+
+		btrfs_release_path(root, path);
+		key.offset++;
+	}
+
+	/* We've succeeded in going through all extents; set the final size. */
+	ret = compressed_size;
+
+out:
+	btrfs_release_path(root, path);
+	unlock_extent(&BTRFS_I(inode)->io_tree, 0, len, GFP_NOFS);
+	mutex_unlock(&inode->i_mutex);
+	btrfs_free_path(path);
+	return ret;
+}
+
 static long btrfs_ioctl_clone_range(struct file *file, void __user *argp)
 {
 	struct btrfs_ioctl_clone_range_args args;
@@ -1122,6 +1233,8 @@ long btrfs_ioctl(struct file *file, unsigned int
 		return btrfs_ioctl_trans_start(file);
 	case BTRFS_IOC_TRANS_END:
 		return btrfs_ioctl_trans_end(file);
+	case BTRFS_IOC_COMPR_SIZE:
+		return btrfs_ioctl_compsize(file);
 	case BTRFS_IOC_SYNC:
 		btrfs_sync_fs(file->f_dentry->d_sb, 1);
 		return 0;
diff --git a/fs/btrfs/ioctl.h b/fs/btrfs/ioctl.h
index b320b10..bd2f866 100644
--- a/fs/btrfs/ioctl.h
+++ b/fs/btrfs/ioctl.h
@@ -66,4 +66,5 @@ struct btrfs_ioctl_clone_range_args {
 #define BTRFS_IOC_SUBVOL_CREATE _IOW(BTRFS_IOCTL_MAGIC, 14, \
 				   struct btrfs_ioctl_vol_args)
 
+#define BTRFS_IOC_COMPR_SIZE	_IO(BTRFS_IOCTL_MAGIC, 15)
 #endif
-- 
Chris Ball   <cjb@laptop.org>

^ permalink raw reply related	[flat|nested] 4+ messages in thread

* Re: [REVIEW] Btrfs: Introduce ioctl for compressed size of file
  2009-04-19  3:56   ` [REVIEW] Btrfs: Introduce ioctl for compressed size of file Chris Ball
@ 2009-04-23 19:20     ` Chris Mason
  0 siblings, 0 replies; 4+ messages in thread
From: Chris Mason @ 2009-04-23 19:20 UTC (permalink / raw)
  To: Chris Ball; +Cc: mp3geek, linux-btrfs

On Sat, 2009-04-18 at 23:56 -0400, Chris Ball wrote:
> Hi,
> 
>    > We need to add an ioctl that reports on the actual size of the
>    > compressed file.
> 
> Here's an attempt at that ioctl, please review.  The search code is
> based on the clone ioctl.  Some specific questions:
> 

Thanks for doing this.

> * Is the first while() loop necessary?

Not really, you could just do:

btrfs_wait_ordered_range(inode, 0, (u64)-1);

> * Are the semantics of returning -EINVAL when called on an FS with
>   compression disabled desirable?
> 

Instead of calling it the compressed size, I'd call it the size used on
disk.  For a compressed file, this will be smaller than the size in ram,
otherwise it'll be the same.

But, the ioctl is returning an unsigned long, which isn't quite big
enough to hold the total possible size of the file on disk.  I'd have it
return the answer in a u64 instead.

-chris



^ permalink raw reply	[flat|nested] 4+ messages in thread

end of thread, other threads:[~2009-04-23 19:20 UTC | newest]

Thread overview: 4+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2009-04-06  6:32 measuring btrfs compression mp3geek
2009-04-07  3:18 ` Chris Mason
2009-04-19  3:56   ` [REVIEW] Btrfs: Introduce ioctl for compressed size of file Chris Ball
2009-04-23 19:20     ` Chris Mason

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox