Whamcloud - gitweb
LU-2658 llite: too many arguments in generic_file_llseek_size
[fs/lustre-release.git] / ldiskfs / kernel_patches / patches / ext4-fiemap-2.6-rhel6.patch
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.
5
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)
18  
19 Index: linux-stage/fs/ext4/ioctl.c
20 ===================================================================
21 --- linux-stage.orig/fs/ext4/ioctl.c
22 +++ linux-stage/fs/ext4/ioctl.c
23 @@ -18,6 +18,71 @@
24  #include "ext4_jbd2.h"
25  #include "ext4.h"
26  
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))
29 +
30 +static int fiemap_check_ranges(struct super_block *sb,
31 +                              u64 start, u64 len, u64 *new_len)
32 +{
33 +       *new_len = len;
34 +
35 +       if (len == 0)
36 +               return -EINVAL;
37 +
38 +       if (start > sb->s_maxbytes)
39 +               return -EFBIG;
40 +
41 +       /*
42 +        * Shrink request scope to what the fs can actually handle.
43 +        */
44 +       if ((len > sb->s_maxbytes) ||
45 +           (sb->s_maxbytes - len) < start)
46 +               *new_len = sb->s_maxbytes - start;
47 +
48 +       return 0;
49 +}
50 +
51 +int ioctl_fiemap(struct inode *inode, struct file *filp, unsigned long arg)
52 +{
53 +       struct fiemap fiemap;
54 +       u64 len;
55 +       struct fiemap_extent_info fieinfo = {0, };
56 +       struct super_block *sb = inode->i_sb;
57 +       int error = 0;
58 +
59 +       if (copy_from_user(&fiemap, (struct fiemap __user *) arg,
60 +                          sizeof(struct fiemap)))
61 +                return -EFAULT;
62 +
63 +       if (fiemap.fm_extent_count > FIEMAP_MAX_EXTENTS)
64 +               return -EINVAL;
65 +
66 +       error = fiemap_check_ranges(sb, fiemap.fm_start, fiemap.fm_length,
67 +                                   &len);
68 +       if (error)
69 +               return error;
70 +
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));
74 +
75 +       if (fiemap.fm_extent_count != 0 &&
76 +           !access_ok(VERIFY_WRITE, (void *)arg,
77 +                      offsetof(typeof(fiemap), fm_extents[fiemap.fm_extent_count])))
78 +               return -EFAULT;
79 +
80 +       if (fieinfo.fi_flags & FIEMAP_FLAG_SYNC)
81 +               filemap_write_and_wait(inode->i_mapping);
82 +
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)))
87 +               error = -EFAULT;
88 +
89 +       return error;
90 +}
91 +
92  long ext4_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
93  {
94         struct inode *inode = filp->f_dentry->d_inode;
95 @@ -330,6 +395,9 @@ mext_out:
96                 mnt_drop_write(filp->f_path.mnt);
97                 return err;
98         }
99 +       case EXT4_IOC_FIEMAP: {
100 +               return ioctl_fiemap(inode, filp, arg);
101 +       }
102  
103         default:
104                 return -ENOTTY;
105 Index: linux-stage/fs/ext4/fiemap.h
106 ===================================================================
107 --- /dev/null
108 +++ linux-stage/fs/ext4/fiemap.h
109 @@ -0,0 +1,2 @@
110 +
111 +#include_next <fiemap.h>