diff options
| author | Linus Torvalds <torvalds@linux-foundation.org> | 2010-10-21 15:39:53 -0400 |
|---|---|---|
| committer | Linus Torvalds <torvalds@linux-foundation.org> | 2010-10-21 15:39:53 -0400 |
| commit | f6f0a6d6a7258eff41fd202fc70df18271a2de79 (patch) | |
| tree | a32040d8cc6e06e056e184e35ed4729e28a244d8 /fs/gfs2/ops_inode.c | |
| parent | 2017bd19454ea7cdae19922d15b6930f6c8088a2 (diff) | |
| parent | 33027af637da3f69bd17488cc3e68493c9052a7d (diff) | |
Merge git://git.kernel.org/pub/scm/linux/kernel/git/steve/gfs2-2.6-nmw
* git://git.kernel.org/pub/scm/linux/kernel/git/steve/gfs2-2.6-nmw: (22 commits)
GFS2: fixed typo
GFS2: Fix type mapping for demote_rq interface
GFS2 fatal: filesystem consistency error on rename
GFS2: Improve journal allocation via sysfs
GFS2: Add "norecovery" mount option as a synonym for "spectator"
GFS2: Fix spectator umount issue
GFS2: Fix compiler warning from previous patch
GFS2: reserve more blocks for transactions
GFS2: Fix journal check for spectator mounts
GFS2: Remove upgrade mount option
GFS2: Remove localcaching mount option
GFS2: Remove ignore_local_fs mount argument
GFS2: Make . and .. qstrs constant
GFS2: Use new workqueue scheme
GFS2: Update handling of DLM return codes to match reality
GFS2: Don't enforce min hold time when two demotes occur in rapid succession
GFS2: Fix whitespace in previous patch
GFS2: fallocate support
GFS2: Add a bug trap in allocation code
GFS2: No longer experimental
...
Diffstat (limited to 'fs/gfs2/ops_inode.c')
| -rw-r--r-- | fs/gfs2/ops_inode.c | 326 |
1 files changed, 274 insertions, 52 deletions
diff --git a/fs/gfs2/ops_inode.c b/fs/gfs2/ops_inode.c index 1009be2c9737..0534510200d5 100644 --- a/fs/gfs2/ops_inode.c +++ b/fs/gfs2/ops_inode.c | |||
| @@ -18,6 +18,8 @@ | |||
| 18 | #include <linux/gfs2_ondisk.h> | 18 | #include <linux/gfs2_ondisk.h> |
| 19 | #include <linux/crc32.h> | 19 | #include <linux/crc32.h> |
| 20 | #include <linux/fiemap.h> | 20 | #include <linux/fiemap.h> |
| 21 | #include <linux/swap.h> | ||
| 22 | #include <linux/falloc.h> | ||
| 21 | #include <asm/uaccess.h> | 23 | #include <asm/uaccess.h> |
| 22 | 24 | ||
| 23 | #include "gfs2.h" | 25 | #include "gfs2.h" |
| @@ -217,7 +219,7 @@ static int gfs2_link(struct dentry *old_dentry, struct inode *dir, | |||
| 217 | goto out_gunlock_q; | 219 | goto out_gunlock_q; |
| 218 | 220 | ||
| 219 | error = gfs2_trans_begin(sdp, sdp->sd_max_dirres + | 221 | error = gfs2_trans_begin(sdp, sdp->sd_max_dirres + |
| 220 | al->al_rgd->rd_length + | 222 | gfs2_rg_blocks(al) + |
| 221 | 2 * RES_DINODE + RES_STATFS + | 223 | 2 * RES_DINODE + RES_STATFS + |
| 222 | RES_QUOTA, 0); | 224 | RES_QUOTA, 0); |
| 223 | if (error) | 225 | if (error) |
| @@ -406,7 +408,6 @@ static int gfs2_symlink(struct inode *dir, struct dentry *dentry, | |||
| 406 | 408 | ||
| 407 | ip = ghs[1].gh_gl->gl_object; | 409 | ip = ghs[1].gh_gl->gl_object; |
| 408 | 410 | ||
| 409 | ip->i_disksize = size; | ||
| 410 | i_size_write(inode, size); | 411 | i_size_write(inode, size); |
| 411 | 412 | ||
| 412 | error = gfs2_meta_inode_buffer(ip, &dibh); | 413 | error = gfs2_meta_inode_buffer(ip, &dibh); |
| @@ -461,7 +462,7 @@ static int gfs2_mkdir(struct inode *dir, struct dentry *dentry, int mode) | |||
| 461 | ip = ghs[1].gh_gl->gl_object; | 462 | ip = ghs[1].gh_gl->gl_object; |
| 462 | 463 | ||
| 463 | ip->i_inode.i_nlink = 2; | 464 | ip->i_inode.i_nlink = 2; |
| 464 | ip->i_disksize = sdp->sd_sb.sb_bsize - sizeof(struct gfs2_dinode); | 465 | i_size_write(inode, sdp->sd_sb.sb_bsize - sizeof(struct gfs2_dinode)); |
| 465 | ip->i_diskflags |= GFS2_DIF_JDATA; | 466 | ip->i_diskflags |= GFS2_DIF_JDATA; |
| 466 | ip->i_entries = 2; | 467 | ip->i_entries = 2; |
| 467 | 468 | ||
| @@ -470,18 +471,15 @@ static int gfs2_mkdir(struct inode *dir, struct dentry *dentry, int mode) | |||
| 470 | if (!gfs2_assert_withdraw(sdp, !error)) { | 471 | if (!gfs2_assert_withdraw(sdp, !error)) { |
| 471 | struct gfs2_dinode *di = (struct gfs2_dinode *)dibh->b_data; | 472 | struct gfs2_dinode *di = (struct gfs2_dinode *)dibh->b_data; |
| 472 | struct gfs2_dirent *dent = (struct gfs2_dirent *)(di+1); | 473 | struct gfs2_dirent *dent = (struct gfs2_dirent *)(di+1); |
| 473 | struct qstr str; | ||
| 474 | 474 | ||
| 475 | gfs2_str2qstr(&str, "."); | ||
| 476 | gfs2_trans_add_bh(ip->i_gl, dibh, 1); | 475 | gfs2_trans_add_bh(ip->i_gl, dibh, 1); |
| 477 | gfs2_qstr2dirent(&str, GFS2_DIRENT_SIZE(str.len), dent); | 476 | gfs2_qstr2dirent(&gfs2_qdot, GFS2_DIRENT_SIZE(gfs2_qdot.len), dent); |
| 478 | dent->de_inum = di->di_num; /* already GFS2 endian */ | 477 | dent->de_inum = di->di_num; /* already GFS2 endian */ |
| 479 | dent->de_type = cpu_to_be16(DT_DIR); | 478 | dent->de_type = cpu_to_be16(DT_DIR); |
| 480 | di->di_entries = cpu_to_be32(1); | 479 | di->di_entries = cpu_to_be32(1); |
| 481 | 480 | ||
| 482 | gfs2_str2qstr(&str, ".."); | ||
| 483 | dent = (struct gfs2_dirent *)((char*)dent + GFS2_DIRENT_SIZE(1)); | 481 | dent = (struct gfs2_dirent *)((char*)dent + GFS2_DIRENT_SIZE(1)); |
| 484 | gfs2_qstr2dirent(&str, dibh->b_size - GFS2_DIRENT_SIZE(1) - sizeof(struct gfs2_dinode), dent); | 482 | gfs2_qstr2dirent(&gfs2_qdotdot, dibh->b_size - GFS2_DIRENT_SIZE(1) - sizeof(struct gfs2_dinode), dent); |
| 485 | 483 | ||
| 486 | gfs2_inum_out(dip, dent); | 484 | gfs2_inum_out(dip, dent); |
| 487 | dent->de_type = cpu_to_be16(DT_DIR); | 485 | dent->de_type = cpu_to_be16(DT_DIR); |
| @@ -522,7 +520,6 @@ static int gfs2_mkdir(struct inode *dir, struct dentry *dentry, int mode) | |||
| 522 | static int gfs2_rmdiri(struct gfs2_inode *dip, const struct qstr *name, | 520 | static int gfs2_rmdiri(struct gfs2_inode *dip, const struct qstr *name, |
| 523 | struct gfs2_inode *ip) | 521 | struct gfs2_inode *ip) |
| 524 | { | 522 | { |
| 525 | struct qstr dotname; | ||
| 526 | int error; | 523 | int error; |
| 527 | 524 | ||
| 528 | if (ip->i_entries != 2) { | 525 | if (ip->i_entries != 2) { |
| @@ -539,13 +536,11 @@ static int gfs2_rmdiri(struct gfs2_inode *dip, const struct qstr *name, | |||
| 539 | if (error) | 536 | if (error) |
| 540 | return error; | 537 | return error; |
| 541 | 538 | ||
| 542 | gfs2_str2qstr(&dotname, "."); | 539 | error = gfs2_dir_del(ip, &gfs2_qdot); |
| 543 | error = gfs2_dir_del(ip, &dotname); | ||
| 544 | if (error) | 540 | if (error) |
| 545 | return error; | 541 | return error; |
| 546 | 542 | ||
| 547 | gfs2_str2qstr(&dotname, ".."); | 543 | error = gfs2_dir_del(ip, &gfs2_qdotdot); |
| 548 | error = gfs2_dir_del(ip, &dotname); | ||
| 549 | if (error) | 544 | if (error) |
| 550 | return error; | 545 | return error; |
| 551 | 546 | ||
| @@ -694,11 +689,8 @@ static int gfs2_ok_to_move(struct gfs2_inode *this, struct gfs2_inode *to) | |||
| 694 | struct inode *dir = &to->i_inode; | 689 | struct inode *dir = &to->i_inode; |
| 695 | struct super_block *sb = dir->i_sb; | 690 | struct super_block *sb = dir->i_sb; |
| 696 | struct inode *tmp; | 691 | struct inode *tmp; |
| 697 | struct qstr dotdot; | ||
| 698 | int error = 0; | 692 | int error = 0; |
| 699 | 693 | ||
| 700 | gfs2_str2qstr(&dotdot, ".."); | ||
| 701 | |||
| 702 | igrab(dir); | 694 | igrab(dir); |
| 703 | 695 | ||
| 704 | for (;;) { | 696 | for (;;) { |
| @@ -711,7 +703,7 @@ static int gfs2_ok_to_move(struct gfs2_inode *this, struct gfs2_inode *to) | |||
| 711 | break; | 703 | break; |
| 712 | } | 704 | } |
| 713 | 705 | ||
| 714 | tmp = gfs2_lookupi(dir, &dotdot, 1); | 706 | tmp = gfs2_lookupi(dir, &gfs2_qdotdot, 1); |
| 715 | if (IS_ERR(tmp)) { | 707 | if (IS_ERR(tmp)) { |
| 716 | error = PTR_ERR(tmp); | 708 | error = PTR_ERR(tmp); |
| 717 | break; | 709 | break; |
| @@ -744,7 +736,7 @@ static int gfs2_rename(struct inode *odir, struct dentry *odentry, | |||
| 744 | struct gfs2_inode *ip = GFS2_I(odentry->d_inode); | 736 | struct gfs2_inode *ip = GFS2_I(odentry->d_inode); |
| 745 | struct gfs2_inode *nip = NULL; | 737 | struct gfs2_inode *nip = NULL; |
| 746 | struct gfs2_sbd *sdp = GFS2_SB(odir); | 738 | struct gfs2_sbd *sdp = GFS2_SB(odir); |
| 747 | struct gfs2_holder ghs[5], r_gh = { .gh_gl = NULL, }; | 739 | struct gfs2_holder ghs[5], r_gh = { .gh_gl = NULL, }, ri_gh; |
| 748 | struct gfs2_rgrpd *nrgd; | 740 | struct gfs2_rgrpd *nrgd; |
| 749 | unsigned int num_gh; | 741 | unsigned int num_gh; |
| 750 | int dir_rename = 0; | 742 | int dir_rename = 0; |
| @@ -758,6 +750,9 @@ static int gfs2_rename(struct inode *odir, struct dentry *odentry, | |||
| 758 | return 0; | 750 | return 0; |
| 759 | } | 751 | } |
| 760 | 752 | ||
| 753 | error = gfs2_rindex_hold(sdp, &ri_gh); | ||
| 754 | if (error) | ||
| 755 | return error; | ||
| 761 | 756 | ||
| 762 | if (odip != ndip) { | 757 | if (odip != ndip) { |
| 763 | error = gfs2_glock_nq_init(sdp->sd_rename_gl, LM_ST_EXCLUSIVE, | 758 | error = gfs2_glock_nq_init(sdp->sd_rename_gl, LM_ST_EXCLUSIVE, |
| @@ -887,12 +882,12 @@ static int gfs2_rename(struct inode *odir, struct dentry *odentry, | |||
| 887 | 882 | ||
| 888 | al->al_requested = sdp->sd_max_dirres; | 883 | al->al_requested = sdp->sd_max_dirres; |
| 889 | 884 | ||
| 890 | error = gfs2_inplace_reserve(ndip); | 885 | error = gfs2_inplace_reserve_ri(ndip); |
| 891 | if (error) | 886 | if (error) |
| 892 | goto out_gunlock_q; | 887 | goto out_gunlock_q; |
| 893 | 888 | ||
| 894 | error = gfs2_trans_begin(sdp, sdp->sd_max_dirres + | 889 | error = gfs2_trans_begin(sdp, sdp->sd_max_dirres + |
| 895 | al->al_rgd->rd_length + | 890 | gfs2_rg_blocks(al) + |
| 896 | 4 * RES_DINODE + 4 * RES_LEAF + | 891 | 4 * RES_DINODE + 4 * RES_LEAF + |
| 897 | RES_STATFS + RES_QUOTA + 4, 0); | 892 | RES_STATFS + RES_QUOTA + 4, 0); |
| 898 | if (error) | 893 | if (error) |
| @@ -920,9 +915,6 @@ static int gfs2_rename(struct inode *odir, struct dentry *odentry, | |||
| 920 | } | 915 | } |
| 921 | 916 | ||
| 922 | if (dir_rename) { | 917 | if (dir_rename) { |
| 923 | struct qstr name; | ||
| 924 | gfs2_str2qstr(&name, ".."); | ||
| 925 | |||
| 926 | error = gfs2_change_nlink(ndip, +1); | 918 | error = gfs2_change_nlink(ndip, +1); |
| 927 | if (error) | 919 | if (error) |
| 928 | goto out_end_trans; | 920 | goto out_end_trans; |
| @@ -930,7 +922,7 @@ static int gfs2_rename(struct inode *odir, struct dentry *odentry, | |||
| 930 | if (error) | 922 | if (error) |
| 931 | goto out_end_trans; | 923 | goto out_end_trans; |
| 932 | 924 | ||
| 933 | error = gfs2_dir_mvino(ip, &name, ndip, DT_DIR); | 925 | error = gfs2_dir_mvino(ip, &gfs2_qdotdot, ndip, DT_DIR); |
| 934 | if (error) | 926 | if (error) |
| 935 | goto out_end_trans; | 927 | goto out_end_trans; |
| 936 | } else { | 928 | } else { |
| @@ -972,6 +964,7 @@ out_gunlock_r: | |||
| 972 | if (r_gh.gh_gl) | 964 | if (r_gh.gh_gl) |
| 973 | gfs2_glock_dq_uninit(&r_gh); | 965 | gfs2_glock_dq_uninit(&r_gh); |
| 974 | out: | 966 | out: |
| 967 | gfs2_glock_dq_uninit(&ri_gh); | ||
| 975 | return error; | 968 | return error; |
| 976 | } | 969 | } |
| 977 | 970 | ||
| @@ -990,7 +983,7 @@ static void *gfs2_follow_link(struct dentry *dentry, struct nameidata *nd) | |||
| 990 | struct gfs2_inode *ip = GFS2_I(dentry->d_inode); | 983 | struct gfs2_inode *ip = GFS2_I(dentry->d_inode); |
| 991 | struct gfs2_holder i_gh; | 984 | struct gfs2_holder i_gh; |
| 992 | struct buffer_head *dibh; | 985 | struct buffer_head *dibh; |
| 993 | unsigned int x; | 986 | unsigned int x, size; |
| 994 | char *buf; | 987 | char *buf; |
| 995 | int error; | 988 | int error; |
| 996 | 989 | ||
| @@ -1002,7 +995,8 @@ static void *gfs2_follow_link(struct dentry *dentry, struct nameidata *nd) | |||
| 1002 | return NULL; | 995 | return NULL; |
| 1003 | } | 996 | } |
| 1004 | 997 | ||
| 1005 | if (!ip->i_disksize) { | 998 | size = (unsigned int)i_size_read(&ip->i_inode); |
| 999 | if (size == 0) { | ||
| 1006 | gfs2_consist_inode(ip); | 1000 | gfs2_consist_inode(ip); |
| 1007 | buf = ERR_PTR(-EIO); | 1001 | buf = ERR_PTR(-EIO); |
| 1008 | goto out; | 1002 | goto out; |
| @@ -1014,7 +1008,7 @@ static void *gfs2_follow_link(struct dentry *dentry, struct nameidata *nd) | |||
| 1014 | goto out; | 1008 | goto out; |
| 1015 | } | 1009 | } |
| 1016 | 1010 | ||
| 1017 | x = ip->i_disksize + 1; | 1011 | x = size + 1; |
| 1018 | buf = kmalloc(x, GFP_NOFS); | 1012 | buf = kmalloc(x, GFP_NOFS); |
| 1019 | if (!buf) | 1013 | if (!buf) |
| 1020 | buf = ERR_PTR(-ENOMEM); | 1014 | buf = ERR_PTR(-ENOMEM); |
| @@ -1071,30 +1065,6 @@ int gfs2_permission(struct inode *inode, int mask) | |||
| 1071 | return error; | 1065 | return error; |
| 1072 | } | 1066 | } |
| 1073 | 1067 | ||
| 1074 | /* | ||
| 1075 | * XXX(truncate): the truncate_setsize calls should be moved to the end. | ||
| 1076 | */ | ||
| 1077 | static int setattr_size(struct inode *inode, struct iattr *attr) | ||
| 1078 | { | ||
| 1079 | struct gfs2_inode *ip = GFS2_I(inode); | ||
| 1080 | struct gfs2_sbd *sdp = GFS2_SB(inode); | ||
| 1081 | int error; | ||
| 1082 | |||
| 1083 | if (attr->ia_size != ip->i_disksize) { | ||
| 1084 | error = gfs2_trans_begin(sdp, 0, sdp->sd_jdesc->jd_blocks); | ||
| 1085 | if (error) | ||
| 1086 | return error; | ||
| 1087 | truncate_setsize(inode, attr->ia_size); | ||
| 1088 | gfs2_trans_end(sdp); | ||
| 1089 | } | ||
| 1090 | |||
| 1091 | error = gfs2_truncatei(ip, attr->ia_size); | ||
| 1092 | if (error && (inode->i_size != ip->i_disksize)) | ||
| 1093 | i_size_write(inode, ip->i_disksize); | ||
| 1094 | |||
| 1095 | return error; | ||
| 1096 | } | ||
| 1097 | |||
| 1098 | static int setattr_chown(struct inode *inode, struct iattr *attr) | 1068 | static int setattr_chown(struct inode *inode, struct iattr *attr) |
| 1099 | { | 1069 | { |
| 1100 | struct gfs2_inode *ip = GFS2_I(inode); | 1070 | struct gfs2_inode *ip = GFS2_I(inode); |
| @@ -1195,7 +1165,7 @@ static int gfs2_setattr(struct dentry *dentry, struct iattr *attr) | |||
| 1195 | goto out; | 1165 | goto out; |
| 1196 | 1166 | ||
| 1197 | if (attr->ia_valid & ATTR_SIZE) | 1167 | if (attr->ia_valid & ATTR_SIZE) |
| 1198 | error = setattr_size(inode, attr); | 1168 | error = gfs2_setattr_size(inode, attr->ia_size); |
| 1199 | else if (attr->ia_valid & (ATTR_UID | ATTR_GID)) | 1169 | else if (attr->ia_valid & (ATTR_UID | ATTR_GID)) |
| 1200 | error = setattr_chown(inode, attr); | 1170 | error = setattr_chown(inode, attr); |
| 1201 | else if ((attr->ia_valid & ATTR_MODE) && IS_POSIXACL(inode)) | 1171 | else if ((attr->ia_valid & ATTR_MODE) && IS_POSIXACL(inode)) |
| @@ -1301,6 +1271,257 @@ static int gfs2_removexattr(struct dentry *dentry, const char *name) | |||
| 1301 | return ret; | 1271 | return ret; |
| 1302 | } | 1272 | } |
| 1303 | 1273 | ||
| 1274 | static void empty_write_end(struct page *page, unsigned from, | ||
| 1275 | unsigned to) | ||
| 1276 | { | ||
| 1277 | struct gfs2_inode *ip = GFS2_I(page->mapping->host); | ||
| 1278 | |||
| 1279 | page_zero_new_buffers(page, from, to); | ||
| 1280 | flush_dcache_page(page); | ||
| 1281 | mark_page_accessed(page); | ||
| 1282 | |||
| 1283 | if (!gfs2_is_writeback(ip)) | ||
| 1284 | gfs2_page_add_databufs(ip, page, from, to); | ||
| 1285 | |||
| 1286 | block_commit_write(page, from, to); | ||
| 1287 | } | ||
| 1288 | |||
| 1289 | |||
| 1290 | static int write_empty_blocks(struct page *page, unsigned from, unsigned to) | ||
| 1291 | { | ||
| 1292 | unsigned start, end, next; | ||
| 1293 | struct buffer_head *bh, *head; | ||
| 1294 | int error; | ||
| 1295 | |||
| 1296 | if (!page_has_buffers(page)) { | ||
| 1297 | error = block_prepare_write(page, from, to, gfs2_block_map); | ||
| 1298 | if (unlikely(error)) | ||
| 1299 | return error; | ||
| 1300 | |||
| 1301 | empty_write_end(page, from, to); | ||
| 1302 | return 0; | ||
| 1303 | } | ||
| 1304 | |||
| 1305 | bh = head = page_buffers(page); | ||
| 1306 | next = end = 0; | ||
| 1307 | while (next < from) { | ||
| 1308 | next += bh->b_size; | ||
| 1309 | bh = bh->b_this_page; | ||
| 1310 | } | ||
| 1311 | start = next; | ||
| 1312 | do { | ||
| 1313 | next += bh->b_size; | ||
| 1314 | if (buffer_mapped(bh)) { | ||
| 1315 | if (end) { | ||
| 1316 | error = block_prepare_write(page, start, end, | ||
| 1317 | gfs2_block_map); | ||
| 1318 | if (unlikely(error)) | ||
| 1319 | return error; | ||
| 1320 | empty_write_end(page, start, end); | ||
| 1321 | end = 0; | ||
| 1322 | } | ||
| 1323 | start = next; | ||
| 1324 | } | ||
| 1325 | else | ||
| 1326 | end = next; | ||
| 1327 | bh = bh->b_this_page; | ||
| 1328 | } while (next < to); | ||
| 1329 | |||
| 1330 | if (end) { | ||
| 1331 | error = block_prepare_write(page, start, end, gfs2_block_map); | ||
| 1332 | if (unlikely(error)) | ||
| 1333 | return error; | ||
| 1334 | empty_write_end(page, start, end); | ||
| 1335 | } | ||
| 1336 | |||
| 1337 | return 0; | ||
| 1338 | } | ||
| 1339 | |||
| 1340 | static int fallocate_chunk(struct inode *inode, loff_t offset, loff_t len, | ||
| 1341 | int mode) | ||
| 1342 | { | ||
| 1343 | struct gfs2_inode *ip = GFS2_I(inode); | ||
| 1344 | struct buffer_head *dibh; | ||
| 1345 | int error; | ||
| 1346 | u64 start = offset >> PAGE_CACHE_SHIFT; | ||
| 1347 | unsigned int start_offset = offset & ~PAGE_CACHE_MASK; | ||
| 1348 | u64 end = (offset + len - 1) >> PAGE_CACHE_SHIFT; | ||
| 1349 | pgoff_t curr; | ||
| 1350 | struct page *page; | ||
| 1351 | unsigned int end_offset = (offset + len) & ~PAGE_CACHE_MASK; | ||
| 1352 | unsigned int from, to; | ||
| 1353 | |||
| 1354 | if (!end_offset) | ||
| 1355 | end_offset = PAGE_CACHE_SIZE; | ||
| 1356 | |||
| 1357 | error = gfs2_meta_inode_buffer(ip, &dibh); | ||
| 1358 | if (unlikely(error)) | ||
| 1359 | goto out; | ||
| 1360 | |||
| 1361 | gfs2_trans_add_bh(ip->i_gl, dibh, 1); | ||
| 1362 | |||
| 1363 | if (gfs2_is_stuffed(ip)) { | ||
| 1364 | error = gfs2_unstuff_dinode(ip, NULL); | ||
| 1365 | if (unlikely(error)) | ||
| 1366 | goto out; | ||
| 1367 | } | ||
| 1368 | |||
| 1369 | curr = start; | ||
| 1370 | offset = start << PAGE_CACHE_SHIFT; | ||
| 1371 | from = start_offset; | ||
| 1372 | to = PAGE_CACHE_SIZE; | ||
| 1373 | while (curr <= end) { | ||
| 1374 | page = grab_cache_page_write_begin(inode->i_mapping, curr, | ||
| 1375 | AOP_FLAG_NOFS); | ||
| 1376 | if (unlikely(!page)) { | ||
| 1377 | error = -ENOMEM; | ||
| 1378 | goto out; | ||
| 1379 | } | ||
| 1380 | |||
| 1381 | if (curr == end) | ||
| 1382 | to = end_offset; | ||
| 1383 | error = write_empty_blocks(page, from, to); | ||
| 1384 | if (!error && offset + to > inode->i_size && | ||
| 1385 | !(mode & FALLOC_FL_KEEP_SIZE)) { | ||
| 1386 | i_size_write(inode, offset + to); | ||
| 1387 | } | ||
| 1388 | unlock_page(page); | ||
| 1389 | page_cache_release(page); | ||
| 1390 | if (error) | ||
| 1391 | goto out; | ||
| 1392 | curr++; | ||
| 1393 | offset += PAGE_CACHE_SIZE; | ||
| 1394 | from = 0; | ||
| 1395 | } | ||
| 1396 | |||
| 1397 | gfs2_dinode_out(ip, dibh->b_data); | ||
| 1398 | mark_inode_dirty(inode); | ||
| 1399 | |||
| 1400 | brelse(dibh); | ||
| 1401 | |||
| 1402 | out: | ||
| 1403 | return error; | ||
| 1404 | } | ||
| 1405 | |||
| 1406 | static void calc_max_reserv(struct gfs2_inode *ip, loff_t max, loff_t *len, | ||
| 1407 | unsigned int *data_blocks, unsigned int *ind_blocks) | ||
| 1408 | { | ||
| 1409 | const struct gfs2_sbd *sdp = GFS2_SB(&ip->i_inode); | ||
| 1410 | unsigned int max_blocks = ip->i_alloc->al_rgd->rd_free_clone; | ||
| 1411 | unsigned int tmp, max_data = max_blocks - 3 * (sdp->sd_max_height - 1); | ||
| 1412 | |||
| 1413 | for (tmp = max_data; tmp > sdp->sd_diptrs;) { | ||
| 1414 | tmp = DIV_ROUND_UP(tmp, sdp->sd_inptrs); | ||
| 1415 | max_data -= tmp; | ||
| 1416 | } | ||
| 1417 | /* This calculation isn't the exact reverse of gfs2_write_calc_reserve, | ||
| 1418 | so it might end up with fewer data blocks */ | ||
| 1419 | if (max_data <= *data_blocks) | ||
| 1420 | return; | ||
| 1421 | *data_blocks = max_data; | ||
| 1422 | *ind_blocks = max_blocks - max_data; | ||
| 1423 | *len = ((loff_t)max_data - 3) << sdp->sd_sb.sb_bsize_shift; | ||
| 1424 | if (*len > max) { | ||
| 1425 | *len = max; | ||
| 1426 | gfs2_write_calc_reserv(ip, max, data_blocks, ind_blocks); | ||
| 1427 | } | ||
| 1428 | } | ||
| 1429 | |||
| 1430 | static long gfs2_fallocate(struct inode *inode, int mode, loff_t offset, | ||
| 1431 | loff_t len) | ||
| 1432 | { | ||
| 1433 | struct gfs2_sbd *sdp = GFS2_SB(inode); | ||
| 1434 | struct gfs2_inode *ip = GFS2_I(inode); | ||
| 1435 | unsigned int data_blocks = 0, ind_blocks = 0, rblocks; | ||
| 1436 | loff_t bytes, max_bytes; | ||
| 1437 | struct gfs2_alloc *al; | ||
| 1438 | int error; | ||
| 1439 | loff_t next = (offset + len - 1) >> sdp->sd_sb.sb_bsize_shift; | ||
| 1440 | next = (next + 1) << sdp->sd_sb.sb_bsize_shift; | ||
| 1441 | |||
| 1442 | offset = (offset >> sdp->sd_sb.sb_bsize_shift) << | ||
| 1443 | sdp->sd_sb.sb_bsize_shift; | ||
| 1444 | |||
| 1445 | len = next - offset; | ||
| 1446 | bytes = sdp->sd_max_rg_data * sdp->sd_sb.sb_bsize / 2; | ||
| 1447 | if (!bytes) | ||
| 1448 | bytes = UINT_MAX; | ||
| 1449 | |||
| 1450 | gfs2_holder_init(ip->i_gl, LM_ST_EXCLUSIVE, 0, &ip->i_gh); | ||
| 1451 | error = gfs2_glock_nq(&ip->i_gh); | ||
| 1452 | if (unlikely(error)) | ||
| 1453 | goto out_uninit; | ||
| 1454 | |||
| 1455 | if (!gfs2_write_alloc_required(ip, offset, len)) | ||
| 1456 | goto out_unlock; | ||
| 1457 | |||
| 1458 | while (len > 0) { | ||
| 1459 | if (len < bytes) | ||
| 1460 | bytes = len; | ||
| 1461 | al = gfs2_alloc_get(ip); | ||
| 1462 | if (!al) { | ||
| 1463 | error = -ENOMEM; | ||
| 1464 | goto out_unlock; | ||
| 1465 | } | ||
| 1466 | |||
| 1467 | error = gfs2_quota_lock_check(ip); | ||
| 1468 | if (error) | ||
| 1469 | goto out_alloc_put; | ||
| 1470 | |||
| 1471 | retry: | ||
| 1472 | gfs2_write_calc_reserv(ip, bytes, &data_blocks, &ind_blocks); | ||
| 1473 | |||
| 1474 | al->al_requested = data_blocks + ind_blocks; | ||
| 1475 | error = gfs2_inplace_reserve(ip); | ||
| 1476 | if (error) { | ||
| 1477 | if (error == -ENOSPC && bytes > sdp->sd_sb.sb_bsize) { | ||
| 1478 | bytes >>= 1; | ||
| 1479 | goto retry; | ||
| 1480 | } | ||
| 1481 | goto out_qunlock; | ||
| 1482 | } | ||
| 1483 | max_bytes = bytes; | ||
| 1484 | calc_max_reserv(ip, len, &max_bytes, &data_blocks, &ind_blocks); | ||
| 1485 | al->al_requested = data_blocks + ind_blocks; | ||
| 1486 | |||
| 1487 | rblocks = RES_DINODE + ind_blocks + RES_STATFS + RES_QUOTA + | ||
| 1488 | RES_RG_HDR + gfs2_rg_blocks(al); | ||
| 1489 | if (gfs2_is_jdata(ip)) | ||
| 1490 | rblocks += data_blocks ? data_blocks : 1; | ||
| 1491 | |||
| 1492 | error = gfs2_trans_begin(sdp, rblocks, | ||
| 1493 | PAGE_CACHE_SIZE/sdp->sd_sb.sb_bsize); | ||
| 1494 | if (error) | ||
| 1495 | goto out_trans_fail; | ||
| 1496 | |||
| 1497 | error = fallocate_chunk(inode, offset, max_bytes, mode); | ||
| 1498 | gfs2_trans_end(sdp); | ||
| 1499 | |||
| 1500 | if (error) | ||
| 1501 | goto out_trans_fail; | ||
| 1502 | |||
| 1503 | len -= max_bytes; | ||
| 1504 | offset += max_bytes; | ||
| 1505 | gfs2_inplace_release(ip); | ||
| 1506 | gfs2_quota_unlock(ip); | ||
| 1507 | gfs2_alloc_put(ip); | ||
| 1508 | } | ||
| 1509 | goto out_unlock; | ||
| 1510 | |||
| 1511 | out_trans_fail: | ||
| 1512 | gfs2_inplace_release(ip); | ||
| 1513 | out_qunlock: | ||
| 1514 | gfs2_quota_unlock(ip); | ||
| 1515 | out_alloc_put: | ||
| 1516 | gfs2_alloc_put(ip); | ||
| 1517 | out_unlock: | ||
| 1518 | gfs2_glock_dq(&ip->i_gh); | ||
| 1519 | out_uninit: | ||
| 1520 | gfs2_holder_uninit(&ip->i_gh); | ||
| 1521 | return error; | ||
| 1522 | } | ||
| 1523 | |||
| 1524 | |||
| 1304 | static int gfs2_fiemap(struct inode *inode, struct fiemap_extent_info *fieinfo, | 1525 | static int gfs2_fiemap(struct inode *inode, struct fiemap_extent_info *fieinfo, |
| 1305 | u64 start, u64 len) | 1526 | u64 start, u64 len) |
| 1306 | { | 1527 | { |
| @@ -1351,6 +1572,7 @@ const struct inode_operations gfs2_file_iops = { | |||
| 1351 | .getxattr = gfs2_getxattr, | 1572 | .getxattr = gfs2_getxattr, |
| 1352 | .listxattr = gfs2_listxattr, | 1573 | .listxattr = gfs2_listxattr, |
| 1353 | .removexattr = gfs2_removexattr, | 1574 | .removexattr = gfs2_removexattr, |
| 1575 | .fallocate = gfs2_fallocate, | ||
| 1354 | .fiemap = gfs2_fiemap, | 1576 | .fiemap = gfs2_fiemap, |
| 1355 | }; | 1577 | }; |
| 1356 | 1578 | ||
