diff options
Diffstat (limited to 'fs/ocfs2/aops.c')
-rw-r--r-- | fs/ocfs2/aops.c | 68 |
1 files changed, 66 insertions, 2 deletions
diff --git a/fs/ocfs2/aops.c b/fs/ocfs2/aops.c index ac8c39055717..286af3a11383 100644 --- a/fs/ocfs2/aops.c +++ b/fs/ocfs2/aops.c | |||
@@ -26,6 +26,7 @@ | |||
26 | #include <asm/byteorder.h> | 26 | #include <asm/byteorder.h> |
27 | #include <linux/swap.h> | 27 | #include <linux/swap.h> |
28 | #include <linux/pipe_fs_i.h> | 28 | #include <linux/pipe_fs_i.h> |
29 | #include <linux/mpage.h> | ||
29 | 30 | ||
30 | #define MLOG_MASK_PREFIX ML_FILE_IO | 31 | #define MLOG_MASK_PREFIX ML_FILE_IO |
31 | #include <cluster/masklog.h> | 32 | #include <cluster/masklog.h> |
@@ -139,7 +140,8 @@ static int ocfs2_get_block(struct inode *inode, sector_t iblock, | |||
139 | { | 140 | { |
140 | int err = 0; | 141 | int err = 0; |
141 | unsigned int ext_flags; | 142 | unsigned int ext_flags; |
142 | u64 p_blkno, past_eof; | 143 | u64 max_blocks = bh_result->b_size >> inode->i_blkbits; |
144 | u64 p_blkno, count, past_eof; | ||
143 | struct ocfs2_super *osb = OCFS2_SB(inode->i_sb); | 145 | struct ocfs2_super *osb = OCFS2_SB(inode->i_sb); |
144 | 146 | ||
145 | mlog_entry("(0x%p, %llu, 0x%p, %d)\n", inode, | 147 | mlog_entry("(0x%p, %llu, 0x%p, %d)\n", inode, |
@@ -155,7 +157,7 @@ static int ocfs2_get_block(struct inode *inode, sector_t iblock, | |||
155 | goto bail; | 157 | goto bail; |
156 | } | 158 | } |
157 | 159 | ||
158 | err = ocfs2_extent_map_get_blocks(inode, iblock, &p_blkno, NULL, | 160 | err = ocfs2_extent_map_get_blocks(inode, iblock, &p_blkno, &count, |
159 | &ext_flags); | 161 | &ext_flags); |
160 | if (err) { | 162 | if (err) { |
161 | mlog(ML_ERROR, "Error %d from get_blocks(0x%p, %llu, 1, " | 163 | mlog(ML_ERROR, "Error %d from get_blocks(0x%p, %llu, 1, " |
@@ -164,6 +166,9 @@ static int ocfs2_get_block(struct inode *inode, sector_t iblock, | |||
164 | goto bail; | 166 | goto bail; |
165 | } | 167 | } |
166 | 168 | ||
169 | if (max_blocks < count) | ||
170 | count = max_blocks; | ||
171 | |||
167 | /* | 172 | /* |
168 | * ocfs2 never allocates in this function - the only time we | 173 | * ocfs2 never allocates in this function - the only time we |
169 | * need to use BH_New is when we're extending i_size on a file | 174 | * need to use BH_New is when we're extending i_size on a file |
@@ -178,6 +183,8 @@ static int ocfs2_get_block(struct inode *inode, sector_t iblock, | |||
178 | if (p_blkno && !(ext_flags & OCFS2_EXT_UNWRITTEN)) | 183 | if (p_blkno && !(ext_flags & OCFS2_EXT_UNWRITTEN)) |
179 | map_bh(bh_result, inode->i_sb, p_blkno); | 184 | map_bh(bh_result, inode->i_sb, p_blkno); |
180 | 185 | ||
186 | bh_result->b_size = count << inode->i_blkbits; | ||
187 | |||
181 | if (!ocfs2_sparse_alloc(osb)) { | 188 | if (!ocfs2_sparse_alloc(osb)) { |
182 | if (p_blkno == 0) { | 189 | if (p_blkno == 0) { |
183 | err = -EIO; | 190 | err = -EIO; |
@@ -322,6 +329,62 @@ out: | |||
322 | return ret; | 329 | return ret; |
323 | } | 330 | } |
324 | 331 | ||
332 | /* | ||
333 | * This is used only for read-ahead. Failures or difficult to handle | ||
334 | * situations are safe to ignore. | ||
335 | * | ||
336 | * Right now, we don't bother with BH_Boundary - in-inode extent lists | ||
337 | * are quite large (243 extents on 4k blocks), so most inodes don't | ||
338 | * grow out to a tree. If need be, detecting boundary extents could | ||
339 | * trivially be added in a future version of ocfs2_get_block(). | ||
340 | */ | ||
341 | static int ocfs2_readpages(struct file *filp, struct address_space *mapping, | ||
342 | struct list_head *pages, unsigned nr_pages) | ||
343 | { | ||
344 | int ret, err = -EIO; | ||
345 | struct inode *inode = mapping->host; | ||
346 | struct ocfs2_inode_info *oi = OCFS2_I(inode); | ||
347 | loff_t start; | ||
348 | struct page *last; | ||
349 | |||
350 | /* | ||
351 | * Use the nonblocking flag for the dlm code to avoid page | ||
352 | * lock inversion, but don't bother with retrying. | ||
353 | */ | ||
354 | ret = ocfs2_inode_lock_full(inode, NULL, 0, OCFS2_LOCK_NONBLOCK); | ||
355 | if (ret) | ||
356 | return err; | ||
357 | |||
358 | if (down_read_trylock(&oi->ip_alloc_sem) == 0) { | ||
359 | ocfs2_inode_unlock(inode, 0); | ||
360 | return err; | ||
361 | } | ||
362 | |||
363 | /* | ||
364 | * Don't bother with inline-data. There isn't anything | ||
365 | * to read-ahead in that case anyway... | ||
366 | */ | ||
367 | if (oi->ip_dyn_features & OCFS2_INLINE_DATA_FL) | ||
368 | goto out_unlock; | ||
369 | |||
370 | /* | ||
371 | * Check whether a remote node truncated this file - we just | ||
372 | * drop out in that case as it's not worth handling here. | ||
373 | */ | ||
374 | last = list_entry(pages->prev, struct page, lru); | ||
375 | start = (loff_t)last->index << PAGE_CACHE_SHIFT; | ||
376 | if (start >= i_size_read(inode)) | ||
377 | goto out_unlock; | ||
378 | |||
379 | err = mpage_readpages(mapping, pages, nr_pages, ocfs2_get_block); | ||
380 | |||
381 | out_unlock: | ||
382 | up_read(&oi->ip_alloc_sem); | ||
383 | ocfs2_inode_unlock(inode, 0); | ||
384 | |||
385 | return err; | ||
386 | } | ||
387 | |||
325 | /* Note: Because we don't support holes, our allocation has | 388 | /* Note: Because we don't support holes, our allocation has |
326 | * already happened (allocation writes zeros to the file data) | 389 | * already happened (allocation writes zeros to the file data) |
327 | * so we don't have to worry about ordered writes in | 390 | * so we don't have to worry about ordered writes in |
@@ -1877,6 +1940,7 @@ static int ocfs2_write_end(struct file *file, struct address_space *mapping, | |||
1877 | 1940 | ||
1878 | const struct address_space_operations ocfs2_aops = { | 1941 | const struct address_space_operations ocfs2_aops = { |
1879 | .readpage = ocfs2_readpage, | 1942 | .readpage = ocfs2_readpage, |
1943 | .readpages = ocfs2_readpages, | ||
1880 | .writepage = ocfs2_writepage, | 1944 | .writepage = ocfs2_writepage, |
1881 | .write_begin = ocfs2_write_begin, | 1945 | .write_begin = ocfs2_write_begin, |
1882 | .write_end = ocfs2_write_end, | 1946 | .write_end = ocfs2_write_end, |