1 This patch adds direct EXT4_IOC_FIEMAP support to ldiskfs, for Lustre to call
2 without having to go through do_vfs_ioctl() (which isn't exported, and has a
3 number of other ioctls which are not suitable for Lustre). The actual FIEMAP
4 support is already in the kernel/ext4 for normal usage.
6 Index: linux-stage/fs/ext4/ext4.h
7 ===================================================================
8 --- linux-stage.orig/fs/ext4/ext4.h
9 +++ linux-stage/fs/ext4/ext4.h
10 @@ -405,7 +405,7 @@ struct ext4_new_group_data {
11 #define EXT4_IOC_GROUP_ADD _IOW('f', 8, struct ext4_new_group_input)
12 #define EXT4_IOC_MIGRATE _IO('f', 9)
13 /* note ioctl 10 reserved for an early version of the FIEMAP ioctl */
14 - /* note ioctl 11 reserved for filesystem-independent FIEMAP ioctl */
15 +#define EXT4_IOC_FIEMAP _IOWR('f', 11, struct fiemap)
16 #define EXT4_IOC_ALLOC_DA_BLKS _IO('f', 12)
17 #define EXT4_IOC_MOVE_EXT _IOWR('f', 15, struct move_extent)
19 Index: linux-stage/fs/ext4/ioctl.c
20 ===================================================================
21 --- linux-stage.orig/fs/ext4/ioctl.c
22 +++ linux-stage/fs/ext4/ioctl.c
24 #include "ext4_jbd2.h"
27 +/* So that the fiemap access checks can't overflow on 32 bit machines. */
28 +#define FIEMAP_MAX_EXTENTS (UINT_MAX / sizeof(struct fiemap_extent))
30 +static int fiemap_check_ranges(struct super_block *sb,
31 + u64 start, u64 len, u64 *new_len)
38 + if (start > sb->s_maxbytes)
42 + * Shrink request scope to what the fs can actually handle.
44 + if ((len > sb->s_maxbytes) ||
45 + (sb->s_maxbytes - len) < start)
46 + *new_len = sb->s_maxbytes - start;
51 +int ioctl_fiemap(struct inode *inode, struct file *filp, unsigned long arg)
53 + struct fiemap fiemap;
55 + struct fiemap_extent_info fieinfo = {0, };
56 + struct super_block *sb = inode->i_sb;
59 + if (copy_from_user(&fiemap, (struct fiemap __user *) arg,
60 + sizeof(struct fiemap)))
63 + if (fiemap.fm_extent_count > FIEMAP_MAX_EXTENTS)
66 + error = fiemap_check_ranges(sb, fiemap.fm_start, fiemap.fm_length,
71 + fieinfo.fi_flags = fiemap.fm_flags;
72 + fieinfo.fi_extents_max = fiemap.fm_extent_count;
73 + fieinfo.fi_extents_start = (struct fiemap_extent *)(arg + sizeof(fiemap));
75 + if (fiemap.fm_extent_count != 0 &&
76 + !access_ok(VERIFY_WRITE, (void *)arg,
77 + offsetof(typeof(fiemap), fm_extents[fiemap.fm_extent_count])))
80 + if (fieinfo.fi_flags & FIEMAP_FLAG_SYNC)
81 + filemap_write_and_wait(inode->i_mapping);
83 + error = ext4_fiemap(inode, &fieinfo, fiemap.fm_start, len);
84 + fiemap.fm_flags = fieinfo.fi_flags;
85 + fiemap.fm_mapped_extents = fieinfo.fi_extents_mapped;
86 + if (copy_to_user((char *)arg, &fiemap, sizeof(fiemap)))
92 long ext4_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
94 struct inode *inode = filp->f_dentry->d_inode;
95 @@ -330,6 +395,9 @@ mext_out:
96 mnt_drop_write(filp->f_path.mnt);
99 + case EXT4_IOC_FIEMAP: {
100 + return ioctl_fiemap(inode, filp, arg);
105 Index: linux-stage/fs/ext4/fiemap.h
106 ===================================================================
108 +++ linux-stage/fs/ext4/fiemap.h
111 +#include_next <fiemap.h>