Add ext4-printk-throttling patch
[ext4-patch-queue.git] / generic-fiemap.patch
blobbec0f3b8759453352970f6f56f20970cefd2b77e
1 From: Josef Bacik <jbacik@redhat.com>
3 Any block based fs (this patch includes ext3) just has to declare its own
4 fiemap() function and then call this generic function with its own
5 get_block_t. This works well for block based filesystems that will map
6 multiple contiguous blocks at one time, but will work for filesystems that
7 only map one block at a time, you will just end up with an "extent" for each
8 block. One gotcha is this will not play nicely where there is hole+data
9 after the EOF. This function will assume its hit the end of the data as soon
10 as it hits a hole after the EOF, so if there is any data past that it will
11 not pick that up. AFAIK no block based fs does this anyway, but its in the
12 comments of the function anyway just in case.
14 Signed-off-by: Josef Bacik <jbacik@redhat.com>
15 Signed-off-by: Mark Fasheh <mfasheh@suse.com>
16 ---
17 fs/ext2/ext2.h | 2 +
18 fs/ext2/file.c | 1 +
19 fs/ext2/inode.c | 8 +++
20 fs/ext3/file.c | 1 +
21 fs/ext3/inode.c | 8 +++
22 fs/ioctl.c | 119 +++++++++++++++++++++++++++++++++++++++++++++++
23 include/linux/ext3_fs.h | 2 +
24 include/linux/fs.h | 3 +
25 8 files changed, 144 insertions(+), 0 deletions(-)
27 Index: linux-2.6/fs/ext2/ext2.h
28 ===================================================================
29 --- linux-2.6.orig/fs/ext2/ext2.h 2008-07-07 20:08:38.830291129 -0500
30 +++ linux-2.6/fs/ext2/ext2.h 2008-07-14 16:55:46.403353646 -0500
31 @@ -133,6 +133,8 @@ extern void ext2_truncate (struct inode
32 extern int ext2_setattr (struct dentry *, struct iattr *);
33 extern void ext2_set_inode_flags(struct inode *inode);
34 extern void ext2_get_inode_flags(struct ext2_inode_info *);
35 +extern int ext2_fiemap(struct inode *inode, struct fiemap_extent_info *fieinfo,
36 + u64 start, u64 len);
37 int __ext2_write_begin(struct file *file, struct address_space *mapping,
38 loff_t pos, unsigned len, unsigned flags,
39 struct page **pagep, void **fsdata);
40 Index: linux-2.6/fs/ext2/file.c
41 ===================================================================
42 --- linux-2.6.orig/fs/ext2/file.c 2008-06-05 13:44:20.383046060 -0500
43 +++ linux-2.6/fs/ext2/file.c 2008-07-14 16:55:46.411353467 -0500
44 @@ -86,4 +86,5 @@ const struct inode_operations ext2_file_
45 #endif
46 .setattr = ext2_setattr,
47 .permission = ext2_permission,
48 + .fiemap = ext2_fiemap,
50 Index: linux-2.6/fs/ext2/inode.c
51 ===================================================================
52 --- linux-2.6.orig/fs/ext2/inode.c 2008-07-07 20:08:38.830291129 -0500
53 +++ linux-2.6/fs/ext2/inode.c 2008-07-14 16:55:46.452353760 -0500
54 @@ -31,6 +31,7 @@
55 #include <linux/writeback.h>
56 #include <linux/buffer_head.h>
57 #include <linux/mpage.h>
58 +#include <linux/fiemap.h>
59 #include "ext2.h"
60 #include "acl.h"
61 #include "xip.h"
62 @@ -704,6 +705,13 @@ int ext2_get_block(struct inode *inode,
66 +int ext2_fiemap(struct inode *inode, struct fiemap_extent_info *fieinfo,
67 + u64 start, u64 len)
69 + return generic_block_fiemap(inode, fieinfo, start, len,
70 + ext2_get_block);
73 static int ext2_writepage(struct page *page, struct writeback_control *wbc)
75 return block_write_full_page(page, ext2_get_block, wbc);
76 Index: linux-2.6/fs/ext3/file.c
77 ===================================================================
78 --- linux-2.6.orig/fs/ext3/file.c 2008-06-05 13:44:20.413983372 -0500
79 +++ linux-2.6/fs/ext3/file.c 2008-07-14 16:55:46.493353485 -0500
80 @@ -134,5 +134,6 @@ const struct inode_operations ext3_file_
81 .removexattr = generic_removexattr,
82 #endif
83 .permission = ext3_permission,
84 + .fiemap = ext3_fiemap,
87 Index: linux-2.6/fs/ext3/inode.c
88 ===================================================================
89 --- linux-2.6.orig/fs/ext3/inode.c 2008-06-05 13:44:20.416982997 -0500
90 +++ linux-2.6/fs/ext3/inode.c 2008-07-14 16:55:46.514353977 -0500
91 @@ -36,6 +36,7 @@
92 #include <linux/mpage.h>
93 #include <linux/uio.h>
94 #include <linux/bio.h>
95 +#include <linux/fiemap.h>
96 #include "xattr.h"
97 #include "acl.h"
99 @@ -981,6 +982,13 @@ out:
100 return ret;
103 +int ext3_fiemap(struct inode *inode, struct fiemap_extent_info *fieinfo,
104 + u64 start, u64 len)
106 + return generic_block_fiemap(inode, fieinfo, start, len,
107 + ext3_get_block);
111 * `handle' can be NULL if create is zero
113 Index: linux-2.6/fs/ioctl.c
114 ===================================================================
115 --- linux-2.6.orig/fs/ioctl.c 2008-07-14 16:53:46.019353480 -0500
116 +++ linux-2.6/fs/ioctl.c 2008-07-14 16:55:46.552353665 -0500
117 @@ -13,6 +13,8 @@
118 #include <linux/security.h>
119 #include <linux/module.h>
120 #include <linux/uaccess.h>
121 +#include <linux/writeback.h>
122 +#include <linux/buffer_head.h>
124 #include <asm/ioctls.h>
126 @@ -227,6 +229,123 @@ static int ioctl_fiemap(struct file *fil
127 return error;
130 +#define blk_to_logical(inode, blk) (blk << (inode)->i_blkbits)
131 +#define logical_to_blk(inode, offset) (offset >> (inode)->i_blkbits);
134 + * @inode - the inode to map
135 + * @arg - the pointer to userspace where we copy everything to
136 + * @get_block - the fs's get_block function
138 + * This does FIEMAP for block based inodes. Basically it will just loop
139 + * through get_block until we hit the number of extents we want to map, or we
140 + * go past the end of the file and hit a hole.
142 + * If it is possible to have data blocks beyond a hole past @inode->i_size, then
143 + * please do not use this function, it will stop at the first unmapped block
144 + * beyond i_size
145 + */
146 +int generic_block_fiemap(struct inode *inode,
147 + struct fiemap_extent_info *fieinfo, u64 start,
148 + u64 len, get_block_t *get_block)
150 + struct buffer_head tmp;
151 + unsigned int start_blk;
152 + long long length = 0, map_len = 0;
153 + u64 logical = 0, phys = 0, size = 0;
154 + u32 flags = FIEMAP_EXTENT_MERGED;
155 + int ret = 0;
156 + dev_t dev = inode->i_sb->s_dev;
158 + if ((ret = fiemap_check_flags(fieinfo, FIEMAP_FLAG_SYNC)))
159 + return ret;
161 + start_blk = logical_to_blk(inode, start);
163 + /* guard against change */
164 + mutex_lock(&inode->i_mutex);
166 + length = (long long)min_t(u64, len, i_size_read(inode));
167 + map_len = length;
169 + do {
170 + /*
171 + * we set b_size to the total size we want so it will map as
172 + * many contiguous blocks as possible at once
173 + */
174 + memset(&tmp, 0, sizeof(struct buffer_head));
175 + tmp.b_size = map_len;
177 + ret = get_block(inode, start_blk, &tmp, 0);
178 + if (ret)
179 + break;
181 + /* HOLE */
182 + if (!buffer_mapped(&tmp)) {
183 + /*
184 + * first hole after going past the EOF, this is our
185 + * last extent
186 + */
187 + if (length <= 0) {
188 + flags = FIEMAP_EXTENT_MERGED|FIEMAP_EXTENT_LAST;
189 + ret = fiemap_fill_next_extent(fieinfo, logical,
190 + phys, size,
191 + flags, dev);
192 + break;
195 + length -= blk_to_logical(inode, 1);
197 + /* if we have holes up to/past EOF then we're done */
198 + if (length <= 0)
199 + break;
201 + start_blk++;
202 + } else {
203 + if (length <= 0 && size) {
204 + ret = fiemap_fill_next_extent(fieinfo, logical,
205 + phys, size,
206 + flags, dev);
207 + if (ret)
208 + break;
211 + logical = blk_to_logical(inode, start_blk);
212 + phys = blk_to_logical(inode, tmp.b_blocknr);
213 + size = tmp.b_size;
214 + flags = FIEMAP_EXTENT_MERGED;
216 + length -= tmp.b_size;
217 + start_blk += logical_to_blk(inode, size);
219 + /*
220 + * if we are past the EOF we need to loop again to see
221 + * if there is a hole so we can mark this extent as the
222 + * last one, and if not keep mapping things until we
223 + * find a hole, or we run out of slots in the extent
224 + * array
225 + */
226 + if (length <= 0)
227 + continue;
229 + ret = fiemap_fill_next_extent(fieinfo, logical, phys,
230 + size, flags, dev);
231 + if (ret)
232 + break;
234 + cond_resched();
235 + } while (1);
237 + mutex_unlock(&inode->i_mutex);
239 + /* if ret is 1 then we just hit the end of the extent array */
240 + if (ret == 1)
241 + ret = 0;
243 + return ret;
245 +EXPORT_SYMBOL(generic_block_fiemap);
247 static int file_ioctl(struct file *filp, unsigned int cmd,
248 unsigned long arg)
250 Index: linux-2.6/include/linux/ext3_fs.h
251 ===================================================================
252 --- linux-2.6.orig/include/linux/ext3_fs.h 2008-06-05 13:44:39.555984803 -0500
253 +++ linux-2.6/include/linux/ext3_fs.h 2008-07-14 16:55:46.602353561 -0500
254 @@ -836,6 +836,8 @@ extern void ext3_truncate (struct inode
255 extern void ext3_set_inode_flags(struct inode *);
256 extern void ext3_get_inode_flags(struct ext3_inode_info *);
257 extern void ext3_set_aops(struct inode *inode);
258 +extern int ext3_fiemap(struct inode *inode, struct fiemap_extent_info *fieinfo,
259 + u64 start, u64 len);
261 /* ioctl.c */
262 extern int ext3_ioctl (struct inode *, struct file *, unsigned int,
263 Index: linux-2.6/include/linux/fs.h
264 ===================================================================
265 --- linux-2.6.orig/include/linux/fs.h 2008-07-14 16:53:46.046353840 -0500
266 +++ linux-2.6/include/linux/fs.h 2008-07-14 16:55:46.605354149 -0500
267 @@ -1979,6 +1979,9 @@ extern int vfs_fstat(unsigned int, struc
269 extern int do_vfs_ioctl(struct file *filp, unsigned int fd, unsigned int cmd,
270 unsigned long arg);
271 +extern int generic_block_fiemap(struct inode *inode,
272 + struct fiemap_extent_info *fieinfo, u64 start,
273 + u64 len, get_block_t *get_block);
275 extern void get_filesystem(struct file_system_type *fs);
276 extern void put_filesystem(struct file_system_type *fs);