Whamcloud - gitweb
LU-162 Export ext4_discard_preallocations for ldiskfs
[fs/lustre-release.git] / ldiskfs / kernel_patches / patches / ext4-fiemap-2.6-rhel5.patch
1 diff -rupN linux-2.6.18-164.6.1_1/fs/ext4/ext4.h linux-2.6.18-164.6.1_2/fs/ext4/ext4.h
2 --- linux-2.6.18-164.6.1_1/fs/ext4/ext4.h       2009-12-22 13:07:27.000000000 +0530
3 +++ linux-2.6.18-164.6.1_2/fs/ext4/ext4.h       2009-12-22 13:10:18.000000000 +0530
4 @@ -305,6 +305,7 @@ struct ext4_new_group_data {
5  #define EXT4_IOC_GROUP_EXTEND          _IOW('f', 7, unsigned long)
6  #define EXT4_IOC_GROUP_ADD             _IOW('f', 8, struct ext4_new_group_input)
7  #define EXT4_IOC_MIGRATE               _IO('f', 9)
8 +#define EXT4_IOC_FIEMAP                _IOWR('f', 11, struct fiemap)
9   /* note ioctl 10 reserved for an early version of the FIEMAP ioctl */
10   /* note ioctl 11 reserved for filesystem-independent FIEMAP ioctl */
11  
12 diff -rupN linux-2.6.18-164.6.1_1/fs/ext4/ioctl.c linux-2.6.18-164.6.1_2/fs/ext4/ioctl.c
13 --- linux-2.6.18-164.6.1_1/fs/ext4/ioctl.c      2009-12-22 13:06:51.000000000 +0530
14 +++ linux-2.6.18-164.6.1_2/fs/ext4/ioctl.c      2009-12-22 13:09:45.000000000 +0530
15 @@ -17,6 +17,71 @@
16  #include "ext4_jbd2.h"
17  #include "ext4.h"
18  
19 +/* So that the fiemap access checks can't overflow on 32 bit machines. */
20 +#define FIEMAP_MAX_EXTENTS     (UINT_MAX / sizeof(struct fiemap_extent))
21 +
22 +static int fiemap_check_ranges(struct super_block *sb,
23 +                              u64 start, u64 len, u64 *new_len)
24 +{
25 +       *new_len = len;
26 +
27 +       if (len == 0)
28 +               return -EINVAL;
29 +
30 +       if (start > sb->s_maxbytes)
31 +               return -EFBIG;
32 +
33 +       /*
34 +        * Shrink request scope to what the fs can actually handle.
35 +        */
36 +       if ((len > sb->s_maxbytes) ||
37 +           (sb->s_maxbytes - len) < start)
38 +               *new_len = sb->s_maxbytes - start;
39 +
40 +       return 0;
41 +}
42 +
43 +int ioctl_fiemap(struct inode *inode, struct file *filp, unsigned long arg)
44 +{
45 +       struct fiemap fiemap;
46 +       u64 len;
47 +       struct fiemap_extent_info fieinfo = {0, };
48 +       struct super_block *sb = inode->i_sb;
49 +       int error = 0;
50 +
51 +       if (copy_from_user(&fiemap, (struct fiemap __user *) arg,
52 +                          sizeof(struct fiemap)))
53 +                return -EFAULT;
54 +
55 +       if (fiemap.fm_extent_count > FIEMAP_MAX_EXTENTS)
56 +               return -EINVAL;
57 +
58 +       error = fiemap_check_ranges(sb, fiemap.fm_start, fiemap.fm_length,
59 +                                   &len);
60 +       if (error)
61 +               return error;
62 +
63 +       fieinfo.fi_flags = fiemap.fm_flags;
64 +       fieinfo.fi_extents_max = fiemap.fm_extent_count;
65 +       fieinfo.fi_extents_start = (struct fiemap_extent *)(arg + sizeof(fiemap));
66 +
67 +       if (fiemap.fm_extent_count != 0 &&
68 +           !access_ok(VERIFY_WRITE, (void *)arg,
69 +                      offsetof(typeof(fiemap), fm_extents[fiemap.fm_extent_count])))
70 +               return -EFAULT;
71 +
72 +       if (fieinfo.fi_flags & FIEMAP_FLAG_SYNC)
73 +               filemap_write_and_wait(inode->i_mapping);
74 +
75 +       error = ext4_fiemap(inode, &fieinfo, fiemap.fm_start, len);
76 +       fiemap.fm_flags = fieinfo.fi_flags;
77 +       fiemap.fm_mapped_extents = fieinfo.fi_extents_mapped;
78 +       if (copy_to_user((char *)arg, &fiemap, sizeof(fiemap)))
79 +               error = -EFAULT;
80 +
81 +       return error;
82 +}
83 +
84  long ext4_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
85  {
86         struct inode *inode = filp->f_dentry->d_inode;
87 @@ -249,6 +314,9 @@ flags_out:
88                 mutex_unlock(&(inode->i_mutex));
89                 return err;
90         }
91 +       case EXT4_IOC_FIEMAP: {
92 +               return ioctl_fiemap(inode, filp, arg);
93 +       }
94  
95         default:
96                 return -ENOTTY;