diff options
Diffstat (limited to 'fs')
-rw-r--r-- | fs/gfs2/bmap.c | 49 | ||||
-rw-r--r-- | fs/gfs2/bmap.h | 34 | ||||
-rw-r--r-- | fs/gfs2/ops_address.c | 6 | ||||
-rw-r--r-- | fs/gfs2/ops_file.c | 2 |
4 files changed, 42 insertions, 49 deletions
diff --git a/fs/gfs2/bmap.c b/fs/gfs2/bmap.c index 789f28cfdc20..11ffc56f1f81 100644 --- a/fs/gfs2/bmap.c +++ b/fs/gfs2/bmap.c | |||
@@ -1231,35 +1231,6 @@ int gfs2_file_dealloc(struct gfs2_inode *ip) | |||
1231 | } | 1231 | } |
1232 | 1232 | ||
1233 | /** | 1233 | /** |
1234 | * gfs2_write_calc_reserv - calculate number of blocks needed to write to a file | ||
1235 | * @ip: the file | ||
1236 | * @len: the number of bytes to be written to the file | ||
1237 | * @data_blocks: returns the number of data blocks required | ||
1238 | * @ind_blocks: returns the number of indirect blocks required | ||
1239 | * | ||
1240 | */ | ||
1241 | |||
1242 | void gfs2_write_calc_reserv(struct gfs2_inode *ip, unsigned int len, | ||
1243 | unsigned int *data_blocks, unsigned int *ind_blocks) | ||
1244 | { | ||
1245 | struct gfs2_sbd *sdp = GFS2_SB(&ip->i_inode); | ||
1246 | unsigned int tmp; | ||
1247 | |||
1248 | if (gfs2_is_dir(ip)) { | ||
1249 | *data_blocks = DIV_ROUND_UP(len, sdp->sd_jbsize) + 2; | ||
1250 | *ind_blocks = 3 * (sdp->sd_max_jheight - 1); | ||
1251 | } else { | ||
1252 | *data_blocks = (len >> sdp->sd_sb.sb_bsize_shift) + 3; | ||
1253 | *ind_blocks = 3 * (sdp->sd_max_height - 1); | ||
1254 | } | ||
1255 | |||
1256 | for (tmp = *data_blocks; tmp > sdp->sd_diptrs;) { | ||
1257 | tmp = DIV_ROUND_UP(tmp, sdp->sd_inptrs); | ||
1258 | *ind_blocks += tmp; | ||
1259 | } | ||
1260 | } | ||
1261 | |||
1262 | /** | ||
1263 | * gfs2_write_alloc_required - figure out if a write will require an allocation | 1234 | * gfs2_write_alloc_required - figure out if a write will require an allocation |
1264 | * @ip: the file being written to | 1235 | * @ip: the file being written to |
1265 | * @offset: the offset to write to | 1236 | * @offset: the offset to write to |
@@ -1276,6 +1247,7 @@ int gfs2_write_alloc_required(struct gfs2_inode *ip, u64 offset, | |||
1276 | struct buffer_head bh; | 1247 | struct buffer_head bh; |
1277 | unsigned int shift; | 1248 | unsigned int shift; |
1278 | u64 lblock, lblock_stop, size; | 1249 | u64 lblock, lblock_stop, size; |
1250 | u64 end_of_file; | ||
1279 | 1251 | ||
1280 | *alloc_required = 0; | 1252 | *alloc_required = 0; |
1281 | 1253 | ||
@@ -1291,19 +1263,12 @@ int gfs2_write_alloc_required(struct gfs2_inode *ip, u64 offset, | |||
1291 | 1263 | ||
1292 | *alloc_required = 1; | 1264 | *alloc_required = 1; |
1293 | shift = sdp->sd_sb.sb_bsize_shift; | 1265 | shift = sdp->sd_sb.sb_bsize_shift; |
1294 | if (gfs2_is_dir(ip)) { | 1266 | BUG_ON(gfs2_is_dir(ip)); |
1295 | unsigned int bsize = sdp->sd_jbsize; | 1267 | end_of_file = (ip->i_disksize + sdp->sd_sb.sb_bsize - 1) >> shift; |
1296 | lblock = offset; | 1268 | lblock = offset >> shift; |
1297 | do_div(lblock, bsize); | 1269 | lblock_stop = (offset + len + sdp->sd_sb.sb_bsize - 1) >> shift; |
1298 | lblock_stop = offset + len + bsize - 1; | 1270 | if (lblock_stop > end_of_file) |
1299 | do_div(lblock_stop, bsize); | 1271 | return 0; |
1300 | } else { | ||
1301 | u64 end_of_file = (ip->i_disksize + sdp->sd_sb.sb_bsize - 1) >> shift; | ||
1302 | lblock = offset >> shift; | ||
1303 | lblock_stop = (offset + len + sdp->sd_sb.sb_bsize - 1) >> shift; | ||
1304 | if (lblock_stop > end_of_file) | ||
1305 | return 0; | ||
1306 | } | ||
1307 | 1272 | ||
1308 | size = (lblock_stop - lblock) << shift; | 1273 | size = (lblock_stop - lblock) << shift; |
1309 | do { | 1274 | do { |
diff --git a/fs/gfs2/bmap.h b/fs/gfs2/bmap.h index 4e6cde2943bd..c983177e05ac 100644 --- a/fs/gfs2/bmap.h +++ b/fs/gfs2/bmap.h | |||
@@ -10,10 +10,40 @@ | |||
10 | #ifndef __BMAP_DOT_H__ | 10 | #ifndef __BMAP_DOT_H__ |
11 | #define __BMAP_DOT_H__ | 11 | #define __BMAP_DOT_H__ |
12 | 12 | ||
13 | #include "inode.h" | ||
14 | |||
13 | struct inode; | 15 | struct inode; |
14 | struct gfs2_inode; | 16 | struct gfs2_inode; |
15 | struct page; | 17 | struct page; |
16 | 18 | ||
19 | |||
20 | /** | ||
21 | * gfs2_write_calc_reserv - calculate number of blocks needed to write to a file | ||
22 | * @ip: the file | ||
23 | * @len: the number of bytes to be written to the file | ||
24 | * @data_blocks: returns the number of data blocks required | ||
25 | * @ind_blocks: returns the number of indirect blocks required | ||
26 | * | ||
27 | */ | ||
28 | |||
29 | static inline void gfs2_write_calc_reserv(const struct gfs2_inode *ip, | ||
30 | unsigned int len, | ||
31 | unsigned int *data_blocks, | ||
32 | unsigned int *ind_blocks) | ||
33 | { | ||
34 | const struct gfs2_sbd *sdp = GFS2_SB(&ip->i_inode); | ||
35 | unsigned int tmp; | ||
36 | |||
37 | BUG_ON(gfs2_is_dir(ip)); | ||
38 | *data_blocks = (len >> sdp->sd_sb.sb_bsize_shift) + 3; | ||
39 | *ind_blocks = 3 * (sdp->sd_max_height - 1); | ||
40 | |||
41 | for (tmp = *data_blocks; tmp > sdp->sd_diptrs;) { | ||
42 | tmp = DIV_ROUND_UP(tmp, sdp->sd_inptrs); | ||
43 | *ind_blocks += tmp; | ||
44 | } | ||
45 | } | ||
46 | |||
17 | int gfs2_unstuff_dinode(struct gfs2_inode *ip, struct page *page); | 47 | int gfs2_unstuff_dinode(struct gfs2_inode *ip, struct page *page); |
18 | int gfs2_block_map(struct inode *inode, sector_t lblock, struct buffer_head *bh, int create); | 48 | int gfs2_block_map(struct inode *inode, sector_t lblock, struct buffer_head *bh, int create); |
19 | int gfs2_extent_map(struct inode *inode, u64 lblock, int *new, u64 *dblock, unsigned *extlen); | 49 | int gfs2_extent_map(struct inode *inode, u64 lblock, int *new, u64 *dblock, unsigned *extlen); |
@@ -21,10 +51,6 @@ int gfs2_extent_map(struct inode *inode, u64 lblock, int *new, u64 *dblock, unsi | |||
21 | int gfs2_truncatei(struct gfs2_inode *ip, u64 size); | 51 | int gfs2_truncatei(struct gfs2_inode *ip, u64 size); |
22 | int gfs2_truncatei_resume(struct gfs2_inode *ip); | 52 | int gfs2_truncatei_resume(struct gfs2_inode *ip); |
23 | int gfs2_file_dealloc(struct gfs2_inode *ip); | 53 | int gfs2_file_dealloc(struct gfs2_inode *ip); |
24 | |||
25 | void gfs2_write_calc_reserv(struct gfs2_inode *ip, unsigned int len, | ||
26 | unsigned int *data_blocks, | ||
27 | unsigned int *ind_blocks); | ||
28 | int gfs2_write_alloc_required(struct gfs2_inode *ip, u64 offset, | 54 | int gfs2_write_alloc_required(struct gfs2_inode *ip, u64 offset, |
29 | unsigned int len, int *alloc_required); | 55 | unsigned int len, int *alloc_required); |
30 | 56 | ||
diff --git a/fs/gfs2/ops_address.c b/fs/gfs2/ops_address.c index 0df560f4269a..6e4ea36c6605 100644 --- a/fs/gfs2/ops_address.c +++ b/fs/gfs2/ops_address.c | |||
@@ -625,7 +625,7 @@ static int gfs2_write_begin(struct file *file, struct address_space *mapping, | |||
625 | { | 625 | { |
626 | struct gfs2_inode *ip = GFS2_I(mapping->host); | 626 | struct gfs2_inode *ip = GFS2_I(mapping->host); |
627 | struct gfs2_sbd *sdp = GFS2_SB(mapping->host); | 627 | struct gfs2_sbd *sdp = GFS2_SB(mapping->host); |
628 | unsigned int data_blocks, ind_blocks, rblocks; | 628 | unsigned int data_blocks = 0, ind_blocks = 0, rblocks; |
629 | int alloc_required; | 629 | int alloc_required; |
630 | int error = 0; | 630 | int error = 0; |
631 | struct gfs2_alloc *al; | 631 | struct gfs2_alloc *al; |
@@ -639,11 +639,13 @@ static int gfs2_write_begin(struct file *file, struct address_space *mapping, | |||
639 | if (unlikely(error)) | 639 | if (unlikely(error)) |
640 | goto out_uninit; | 640 | goto out_uninit; |
641 | 641 | ||
642 | gfs2_write_calc_reserv(ip, len, &data_blocks, &ind_blocks); | ||
643 | error = gfs2_write_alloc_required(ip, pos, len, &alloc_required); | 642 | error = gfs2_write_alloc_required(ip, pos, len, &alloc_required); |
644 | if (error) | 643 | if (error) |
645 | goto out_unlock; | 644 | goto out_unlock; |
646 | 645 | ||
646 | if (alloc_required || gfs2_is_jdata(ip)) | ||
647 | gfs2_write_calc_reserv(ip, len, &data_blocks, &ind_blocks); | ||
648 | |||
647 | if (alloc_required) { | 649 | if (alloc_required) { |
648 | al = gfs2_alloc_get(ip); | 650 | al = gfs2_alloc_get(ip); |
649 | if (!al) { | 651 | if (!al) { |
diff --git a/fs/gfs2/ops_file.c b/fs/gfs2/ops_file.c index a6b7a733fd4d..289c5f54ba53 100644 --- a/fs/gfs2/ops_file.c +++ b/fs/gfs2/ops_file.c | |||
@@ -355,7 +355,6 @@ static int gfs2_page_mkwrite(struct vm_area_struct *vma, struct page *page) | |||
355 | goto out; | 355 | goto out; |
356 | 356 | ||
357 | set_bit(GIF_SW_PAGED, &ip->i_flags); | 357 | set_bit(GIF_SW_PAGED, &ip->i_flags); |
358 | gfs2_write_calc_reserv(ip, PAGE_CACHE_SIZE, &data_blocks, &ind_blocks); | ||
359 | ret = gfs2_write_alloc_required(ip, pos, PAGE_CACHE_SIZE, &alloc_required); | 358 | ret = gfs2_write_alloc_required(ip, pos, PAGE_CACHE_SIZE, &alloc_required); |
360 | if (ret || !alloc_required) | 359 | if (ret || !alloc_required) |
361 | goto out_unlock; | 360 | goto out_unlock; |
@@ -367,6 +366,7 @@ static int gfs2_page_mkwrite(struct vm_area_struct *vma, struct page *page) | |||
367 | ret = gfs2_quota_lock_check(ip); | 366 | ret = gfs2_quota_lock_check(ip); |
368 | if (ret) | 367 | if (ret) |
369 | goto out_alloc_put; | 368 | goto out_alloc_put; |
369 | gfs2_write_calc_reserv(ip, PAGE_CACHE_SIZE, &data_blocks, &ind_blocks); | ||
370 | al->al_requested = data_blocks + ind_blocks; | 370 | al->al_requested = data_blocks + ind_blocks; |
371 | ret = gfs2_inplace_reserve(ip); | 371 | ret = gfs2_inplace_reserve(ip); |
372 | if (ret) | 372 | if (ret) |