* [PATCH 4/5] ext4: implement ext4_fiemap
@ 2008-05-25 0:02 Mark Fasheh
2008-05-25 7:51 ` Andreas Dilger
0 siblings, 1 reply; 3+ messages in thread
From: Mark Fasheh @ 2008-05-25 0:02 UTC (permalink / raw)
To: linux-fsdevel; +Cc: Eric Sandeen
From: Eric Sandeen <sandeen@redhat.com>
Hook ext4 to the vfs fiemap interface.
Signed-off-by: Eric Sandeen <sandeen@redhat.com>
---
fs/ext4/ext4.h | 2 +
fs/ext4/ext4_extents.h | 2 +-
fs/ext4/extents.c | 120 +++++++++++++++++++++++++++++++++++++++++++++++-
fs/ext4/file.c | 4 ++
4 files changed, 126 insertions(+), 2 deletions(-)
diff --git a/fs/ext4/ext4.h b/fs/ext4/ext4.h
index 8158083..55f7ca1 100644
--- a/fs/ext4/ext4.h
+++ b/fs/ext4/ext4.h
@@ -383,6 +383,8 @@ struct ext4_inode {
__le32 i_version_hi; /* high 32 bits for 64-bit version */
};
+#define EXT4_FIEMAP_FLAG_INCOMPAT_UNSUPP (FIEMAP_FLAG_INCOMPAT & \
+ ~(FIEMAP_FLAG_LUN_OFFSET))
#define EXT4_EPOCH_BITS 2
#define EXT4_EPOCH_MASK ((1 << EXT4_EPOCH_BITS) - 1)
diff --git a/fs/ext4/ext4_extents.h b/fs/ext4/ext4_extents.h
index 20906b7..c9fabb0 100644
--- a/fs/ext4/ext4_extents.h
+++ b/fs/ext4/ext4_extents.h
@@ -132,7 +132,7 @@ struct ext4_ext_path {
*/
typedef int (*ext_prepare_callback)(struct inode *, struct ext4_ext_path *,
struct ext4_ext_cache *,
- void *);
+ struct ext4_extent *, void *);
#define EXT_CONTINUE 0
#define EXT_BREAK 1
diff --git a/fs/ext4/extents.c b/fs/ext4/extents.c
index ea8dd06..fe7687c 100644
--- a/fs/ext4/extents.c
+++ b/fs/ext4/extents.c
@@ -40,6 +40,7 @@
#include <linux/slab.h>
#include <linux/falloc.h>
#include <asm/uaccess.h>
+#include <linux/fiemap.h>
#include "ext4_jbd2.h"
#include "ext4_extents.h"
@@ -1664,11 +1665,12 @@ int ext4_ext_walk_space(struct inode *inode, ext4_lblk_t block,
}
BUG_ON(cbex.ec_len == 0);
- err = func(inode, path, &cbex, cbdata);
+ err = func(inode, path, &cbex, ex, cbdata);
ext4_ext_drop_refs(path);
if (err < 0)
break;
+
if (err == EXT_REPEAT)
continue;
else if (err == EXT_BREAK) {
@@ -3051,3 +3053,119 @@ retry:
mutex_unlock(&inode->i_mutex);
return ret > 0 ? ret2 : ret;
}
+
+struct fiemap_internal {
+ struct fiemap *fiemap_s;
+ struct fiemap_extent fm_extent;
+ char *cur_ext_ptr;
+ int err;
+};
+
+/*
+ * Callback function called for each extent to gather FIEMAP information.
+ */
+int ext4_ext_fiemap_cb(struct inode *inode, struct ext4_ext_path *path,
+ struct ext4_ext_cache *newex, struct ext4_extent *ex,
+ void *data)
+{
+ struct fiemap_extent_info *fieinfo = data;
+ unsigned long blksize_bits = inode->i_sb->s_blocksize_bits;
+ __u64 logical;
+ __u64 physical;
+ __u64 length;
+ __u32 flags = 0;
+ int error;
+
+ logical = (__u64)newex->ec_block << blksize_bits;
+
+ if (newex->ec_type == EXT4_EXT_CACHE_GAP) {
+ pgoff_t offset;
+ struct page *page;
+ struct buffer_head *bh;
+
+ offset = logical >> PAGE_SHIFT;
+ page = find_get_page(inode->i_mapping, offset);
+ if (!page)
+ return EXT_CONTINUE;
+
+ bh = page_buffers(page);
+
+ if (!bh)
+ return EXT_CONTINUE;
+
+ if (buffer_delay(bh)) {
+ flags |= FIEMAP_EXTENT_DELALLOC;
+ page_cache_release(page);
+ } else {
+ page_cache_release(page);
+ return EXT_CONTINUE;
+ }
+ }
+
+ physical = (__u64)newex->ec_start << blksize_bits;
+ length = (__u64)newex->ec_len << blksize_bits;
+
+ /* Just counting extents? */
+ if (fieinfo->fi_flags & FIEMAP_FLAG_NUM_EXTENTS) {
+ fieinfo->fi_extents_mapped++;
+ return EXT_CONTINUE;
+ }
+
+ if (ex && ext4_ext_is_uninitialized(ex))
+ flags |= FIEMAP_EXTENT_UNWRITTEN;
+
+ /*
+ * If this extent reaches EXT_MAX_BLOCK, it must be last.
+ *
+ * Or if ext4_ext_next_allocated_block is EXT_MAX_BLOCK,
+ * this indicates no more allocated blocks.
+ *
+ * XXX this might miss a single-block extent at EXT_MAX_BLOCK
+ */
+ if (logical + length - 1 == EXT_MAX_BLOCK ||
+ ext4_ext_next_allocated_block(path) == EXT_MAX_BLOCK)
+ flags |= FIEMAP_EXTENT_LAST;
+
+ error = fiemap_fill_next_extent(fieinfo, logical, physical,
+ length, flags, 0);
+ if (error < 0)
+ return error;
+ if (error == 1)
+ return EXT_BREAK;
+
+ return EXT_CONTINUE;
+}
+
+int ext4_fiemap(struct inode *inode, struct fiemap_extent_info *fieinfo,
+ __u64 start, __u64 len)
+{
+ ext4_lblk_t start_blk;
+ ext4_lblk_t len_blks;
+ int err;
+
+ /* fallback to generic here if not extents */
+#warning fix bitmap fallback
+ if (!(EXT4_I(inode)->i_flags & EXT4_EXTENTS_FL))
+ return -EOPNOTSUPP;
+
+#if 0
+ /* bail on unsupported flags for this fs */
+ if (fiemap_s->fm_flags & EXT4_FIEMAP_FLAG_INCOMPAT_UNSUPP)
+ return -EOPNOTSUPP;
+#endif
+
+ start_blk = start >> inode->i_sb->s_blocksize_bits;
+ len_blks = len >> inode->i_sb->s_blocksize_bits;
+
+ /*
+ * Walk the extent tree gathering extent information.
+ * ext4_ext_fiemap_cb will push extents back to user.
+ */
+ down_write(&EXT4_I(inode)->i_data_sem);
+ err = ext4_ext_walk_space(inode, start_blk, len_blks,
+ ext4_ext_fiemap_cb, fieinfo);
+ up_write(&EXT4_I(inode)->i_data_sem);
+
+ return err;
+}
+
diff --git a/fs/ext4/file.c b/fs/ext4/file.c
index 4159be6..99bde24 100644
--- a/fs/ext4/file.c
+++ b/fs/ext4/file.c
@@ -123,6 +123,9 @@ force_commit:
return ret;
}
+extern int ext4_fiemap(struct inode *inode, struct fiemap_extent_info *fieinfo,
+ __u64 start, __u64 len);
+
const struct file_operations ext4_file_operations = {
.llseek = generic_file_llseek,
.read = do_sync_read,
@@ -152,5 +155,6 @@ const struct inode_operations ext4_file_inode_operations = {
#endif
.permission = ext4_permission,
.fallocate = ext4_fallocate,
+ .fiemap = ext4_fiemap,
};
--
1.5.4.1
^ permalink raw reply related [flat|nested] 3+ messages in thread
* Re: [PATCH 4/5] ext4: implement ext4_fiemap
2008-05-25 0:02 [PATCH 4/5] ext4: implement ext4_fiemap Mark Fasheh
@ 2008-05-25 7:51 ` Andreas Dilger
2008-05-25 15:26 ` Eric Sandeen
0 siblings, 1 reply; 3+ messages in thread
From: Andreas Dilger @ 2008-05-25 7:51 UTC (permalink / raw)
To: Mark Fasheh; +Cc: linux-fsdevel, Eric Sandeen
On May 24, 2008 17:02 -0700, Mark Fasheh wrote:
> +#define EXT4_FIEMAP_FLAG_INCOMPAT_UNSUPP (FIEMAP_FLAG_INCOMPAT & \
> + ~(FIEMAP_FLAG_LUN_OFFSET))
Per discussion with Eric, this needs to be changed:
#define EXT4_FIEMAP_FLAG_SUPP (FIEMAP_FLAG_NUM_EXTENTS | FIEMAP_FLAG_SYNC | \
FIEMAP_FLAG_HSM_READ | FIEMAP_FLAG_LUN_ORDER)
> +struct fiemap_internal {
> + struct fiemap *fiemap_s;
> + struct fiemap_extent fm_extent;
> + char *cur_ext_ptr;
> + int err;
> +};
This is no longer used and can be removed (now uses fiemap_extent_info).
> +/*
> + * Callback function called for each extent to gather FIEMAP information.
> + */
> +int ext4_ext_fiemap_cb(struct inode *inode, struct ext4_ext_path *path,
> + struct ext4_ext_cache *newex, struct ext4_extent *ex,
> + void *data)
> +{
> + /* Just counting extents? */
> + if (fieinfo->fi_flags & FIEMAP_FLAG_NUM_EXTENTS) {
> + fieinfo->fi_extents_mapped++;
> + return EXT_CONTINUE;
> + }
This isn't needed anymore, fiemap_fill_next_extent() handles it.
> +int ext4_fiemap(struct inode *inode, struct fiemap_extent_info *fieinfo,
> + __u64 start, __u64 len)
> +{
> + /* fallback to generic here if not extents */
> +#warning fix bitmap fallback
> + if (!(EXT4_I(inode)->i_flags & EXT4_EXTENTS_FL))
> + return -EOPNOTSUPP;
if (!(EXT4_I(inode)->i_flags & EXT4_EXTENTS_FL))
return generic_block_fiemap(inode, fieinfo, start, len,
ext4_get_block);
> +#if 0
> + /* bail on unsupported flags for this fs */
> + if (fiemap_s->fm_flags & EXT4_FIEMAP_FLAG_INCOMPAT_UNSUPP)
> + return -EOPNOTSUPP;
> +#endif
This should be reinstated now that we have come to a decision on the flags:
if (fieinfo->fi_flags & ~EXT4_FIEMAP_FLAG_SUPP) {
fieinfo->fi_flags &= ~EXT4_FIEMAP_FLAG_SUPP;
return -EBADF;
}
Cheers, Andreas
--
Andreas Dilger
Sr. Staff Engineer, Lustre Group
Sun Microsystems of Canada, Inc.
^ permalink raw reply [flat|nested] 3+ messages in thread
* Re: [PATCH 4/5] ext4: implement ext4_fiemap
2008-05-25 7:51 ` Andreas Dilger
@ 2008-05-25 15:26 ` Eric Sandeen
0 siblings, 0 replies; 3+ messages in thread
From: Eric Sandeen @ 2008-05-25 15:26 UTC (permalink / raw)
To: Andreas Dilger; +Cc: Mark Fasheh, linux-fsdevel
Andreas Dilger wrote:
> On May 24, 2008 17:02 -0700, Mark Fasheh wrote:
>> +#define EXT4_FIEMAP_FLAG_INCOMPAT_UNSUPP (FIEMAP_FLAG_INCOMPAT & \
>> + ~(FIEMAP_FLAG_LUN_OFFSET))
>
> Per discussion with Eric, this needs to be changed:
>
> #define EXT4_FIEMAP_FLAG_SUPP (FIEMAP_FLAG_NUM_EXTENTS | FIEMAP_FLAG_SYNC | \
> FIEMAP_FLAG_HSM_READ | FIEMAP_FLAG_LUN_ORDER)
>
Yep, I agree with this and the others, probably should have put "proof
of concept" in the original message; I knew it had warts but didn't want
to hold up Mark's RFE.
Thanks Andreas,
-Eric
>> +struct fiemap_internal {
>> + struct fiemap *fiemap_s;
>> + struct fiemap_extent fm_extent;
>> + char *cur_ext_ptr;
>> + int err;
>> +};
>
> This is no longer used and can be removed (now uses fiemap_extent_info).
>
>> +/*
>> + * Callback function called for each extent to gather FIEMAP information.
>> + */
>> +int ext4_ext_fiemap_cb(struct inode *inode, struct ext4_ext_path *path,
>> + struct ext4_ext_cache *newex, struct ext4_extent *ex,
>> + void *data)
>> +{
>> + /* Just counting extents? */
>> + if (fieinfo->fi_flags & FIEMAP_FLAG_NUM_EXTENTS) {
>> + fieinfo->fi_extents_mapped++;
>> + return EXT_CONTINUE;
>> + }
>
> This isn't needed anymore, fiemap_fill_next_extent() handles it.
>
>
>> +int ext4_fiemap(struct inode *inode, struct fiemap_extent_info *fieinfo,
>> + __u64 start, __u64 len)
>> +{
>> + /* fallback to generic here if not extents */
>> +#warning fix bitmap fallback
>> + if (!(EXT4_I(inode)->i_flags & EXT4_EXTENTS_FL))
>> + return -EOPNOTSUPP;
>
> if (!(EXT4_I(inode)->i_flags & EXT4_EXTENTS_FL))
> return generic_block_fiemap(inode, fieinfo, start, len,
> ext4_get_block);
>
>> +#if 0
>> + /* bail on unsupported flags for this fs */
>> + if (fiemap_s->fm_flags & EXT4_FIEMAP_FLAG_INCOMPAT_UNSUPP)
>> + return -EOPNOTSUPP;
>> +#endif
>
> This should be reinstated now that we have come to a decision on the flags:
>
> if (fieinfo->fi_flags & ~EXT4_FIEMAP_FLAG_SUPP) {
> fieinfo->fi_flags &= ~EXT4_FIEMAP_FLAG_SUPP;
> return -EBADF;
> }
>
>
> Cheers, Andreas
> --
> Andreas Dilger
> Sr. Staff Engineer, Lustre Group
> Sun Microsystems of Canada, Inc.
>
^ permalink raw reply [flat|nested] 3+ messages in thread
end of thread, other threads:[~2008-05-25 15:26 UTC | newest]
Thread overview: 3+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2008-05-25 0:02 [PATCH 4/5] ext4: implement ext4_fiemap Mark Fasheh
2008-05-25 7:51 ` Andreas Dilger
2008-05-25 15:26 ` Eric Sandeen
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).