diff options
| -rw-r--r-- | fs/gfs2/aops.c | 10 | ||||
| -rw-r--r-- | fs/gfs2/bmap.c | 247 | ||||
| -rw-r--r-- | fs/gfs2/bmap.h | 20 | ||||
| -rw-r--r-- | fs/gfs2/ops_inode.c | 26 |
4 files changed, 135 insertions, 168 deletions
diff --git a/fs/gfs2/aops.c b/fs/gfs2/aops.c index 194fe16d8418..f687f25fb7ff 100644 --- a/fs/gfs2/aops.c +++ b/fs/gfs2/aops.c | |||
| @@ -696,13 +696,11 @@ out: | |||
| 696 | 696 | ||
| 697 | page_cache_release(page); | 697 | page_cache_release(page); |
| 698 | 698 | ||
| 699 | /* | 699 | gfs2_trans_end(sdp); |
| 700 | * XXX(truncate): the call below should probably be replaced with | ||
| 701 | * a call to the gfs2-specific truncate blocks helper to actually | ||
| 702 | * release disk blocks.. | ||
| 703 | */ | ||
| 704 | if (pos + len > ip->i_inode.i_size) | 700 | if (pos + len > ip->i_inode.i_size) |
| 705 | truncate_setsize(&ip->i_inode, ip->i_inode.i_size); | 701 | gfs2_trim_blocks(&ip->i_inode); |
| 702 | goto out_trans_fail; | ||
| 703 | |||
| 706 | out_endtrans: | 704 | out_endtrans: |
| 707 | gfs2_trans_end(sdp); | 705 | gfs2_trans_end(sdp); |
| 708 | out_trans_fail: | 706 | out_trans_fail: |
diff --git a/fs/gfs2/bmap.c b/fs/gfs2/bmap.c index 6f482809d1a3..20b971ad4973 100644 --- a/fs/gfs2/bmap.c +++ b/fs/gfs2/bmap.c | |||
| @@ -50,7 +50,7 @@ struct strip_mine { | |||
| 50 | * @ip: the inode | 50 | * @ip: the inode |
| 51 | * @dibh: the dinode buffer | 51 | * @dibh: the dinode buffer |
| 52 | * @block: the block number that was allocated | 52 | * @block: the block number that was allocated |
| 53 | * @private: any locked page held by the caller process | 53 | * @page: The (optional) page. This is looked up if @page is NULL |
| 54 | * | 54 | * |
| 55 | * Returns: errno | 55 | * Returns: errno |
| 56 | */ | 56 | */ |
| @@ -109,8 +109,7 @@ static int gfs2_unstuffer_page(struct gfs2_inode *ip, struct buffer_head *dibh, | |||
| 109 | /** | 109 | /** |
| 110 | * gfs2_unstuff_dinode - Unstuff a dinode when the data has grown too big | 110 | * gfs2_unstuff_dinode - Unstuff a dinode when the data has grown too big |
| 111 | * @ip: The GFS2 inode to unstuff | 111 | * @ip: The GFS2 inode to unstuff |
| 112 | * @unstuffer: the routine that handles unstuffing a non-zero length file | 112 | * @page: The (optional) page. This is looked up if the @page is NULL |
| 113 | * @private: private data for the unstuffer | ||
| 114 | * | 113 | * |
| 115 | * This routine unstuffs a dinode and returns it to a "normal" state such | 114 | * This routine unstuffs a dinode and returns it to a "normal" state such |
| 116 | * that the height can be grown in the traditional way. | 115 | * that the height can be grown in the traditional way. |
| @@ -885,83 +884,14 @@ out: | |||
| 885 | } | 884 | } |
| 886 | 885 | ||
| 887 | /** | 886 | /** |
| 888 | * do_grow - Make a file look bigger than it is | ||
| 889 | * @ip: the inode | ||
| 890 | * @size: the size to set the file to | ||
| 891 | * | ||
| 892 | * Called with an exclusive lock on @ip. | ||
| 893 | * | ||
| 894 | * Returns: errno | ||
| 895 | */ | ||
| 896 | |||
| 897 | static int do_grow(struct gfs2_inode *ip, u64 size) | ||
| 898 | { | ||
| 899 | struct gfs2_sbd *sdp = GFS2_SB(&ip->i_inode); | ||
| 900 | struct gfs2_alloc *al; | ||
| 901 | struct buffer_head *dibh; | ||
| 902 | int error; | ||
| 903 | |||
| 904 | al = gfs2_alloc_get(ip); | ||
| 905 | if (!al) | ||
| 906 | return -ENOMEM; | ||
| 907 | |||
| 908 | error = gfs2_quota_lock_check(ip); | ||
| 909 | if (error) | ||
| 910 | goto out; | ||
| 911 | |||
| 912 | al->al_requested = sdp->sd_max_height + RES_DATA; | ||
| 913 | |||
| 914 | error = gfs2_inplace_reserve(ip); | ||
| 915 | if (error) | ||
| 916 | goto out_gunlock_q; | ||
| 917 | |||
| 918 | error = gfs2_trans_begin(sdp, | ||
| 919 | sdp->sd_max_height + al->al_rgd->rd_length + | ||
| 920 | RES_JDATA + RES_DINODE + RES_STATFS + RES_QUOTA, 0); | ||
| 921 | if (error) | ||
| 922 | goto out_ipres; | ||
| 923 | |||
| 924 | error = gfs2_meta_inode_buffer(ip, &dibh); | ||
| 925 | if (error) | ||
| 926 | goto out_end_trans; | ||
| 927 | |||
| 928 | if (size > sdp->sd_sb.sb_bsize - sizeof(struct gfs2_dinode)) { | ||
| 929 | if (gfs2_is_stuffed(ip)) { | ||
| 930 | error = gfs2_unstuff_dinode(ip, NULL); | ||
| 931 | if (error) | ||
| 932 | goto out_brelse; | ||
| 933 | } | ||
| 934 | } | ||
| 935 | |||
| 936 | ip->i_disksize = size; | ||
| 937 | ip->i_inode.i_mtime = ip->i_inode.i_ctime = CURRENT_TIME; | ||
| 938 | gfs2_trans_add_bh(ip->i_gl, dibh, 1); | ||
| 939 | gfs2_dinode_out(ip, dibh->b_data); | ||
| 940 | |||
| 941 | out_brelse: | ||
| 942 | brelse(dibh); | ||
| 943 | out_end_trans: | ||
| 944 | gfs2_trans_end(sdp); | ||
| 945 | out_ipres: | ||
| 946 | gfs2_inplace_release(ip); | ||
| 947 | out_gunlock_q: | ||
| 948 | gfs2_quota_unlock(ip); | ||
| 949 | out: | ||
| 950 | gfs2_alloc_put(ip); | ||
| 951 | return error; | ||
| 952 | } | ||
| 953 | |||
| 954 | |||
| 955 | /** | ||
| 956 | * gfs2_block_truncate_page - Deal with zeroing out data for truncate | 887 | * gfs2_block_truncate_page - Deal with zeroing out data for truncate |
| 957 | * | 888 | * |
| 958 | * This is partly borrowed from ext3. | 889 | * This is partly borrowed from ext3. |
| 959 | */ | 890 | */ |
| 960 | static int gfs2_block_truncate_page(struct address_space *mapping) | 891 | static int gfs2_block_truncate_page(struct address_space *mapping, loff_t from) |
| 961 | { | 892 | { |
| 962 | struct inode *inode = mapping->host; | 893 | struct inode *inode = mapping->host; |
| 963 | struct gfs2_inode *ip = GFS2_I(inode); | 894 | struct gfs2_inode *ip = GFS2_I(inode); |
| 964 | loff_t from = inode->i_size; | ||
| 965 | unsigned long index = from >> PAGE_CACHE_SHIFT; | 895 | unsigned long index = from >> PAGE_CACHE_SHIFT; |
| 966 | unsigned offset = from & (PAGE_CACHE_SIZE-1); | 896 | unsigned offset = from & (PAGE_CACHE_SIZE-1); |
| 967 | unsigned blocksize, iblock, length, pos; | 897 | unsigned blocksize, iblock, length, pos; |
| @@ -1023,9 +953,11 @@ unlock: | |||
| 1023 | return err; | 953 | return err; |
| 1024 | } | 954 | } |
| 1025 | 955 | ||
| 1026 | static int trunc_start(struct gfs2_inode *ip, u64 size) | 956 | static int trunc_start(struct inode *inode, u64 oldsize, u64 newsize) |
| 1027 | { | 957 | { |
| 1028 | struct gfs2_sbd *sdp = GFS2_SB(&ip->i_inode); | 958 | struct gfs2_inode *ip = GFS2_I(inode); |
| 959 | struct gfs2_sbd *sdp = GFS2_SB(inode); | ||
| 960 | struct address_space *mapping = inode->i_mapping; | ||
| 1029 | struct buffer_head *dibh; | 961 | struct buffer_head *dibh; |
| 1030 | int journaled = gfs2_is_jdata(ip); | 962 | int journaled = gfs2_is_jdata(ip); |
| 1031 | int error; | 963 | int error; |
| @@ -1039,31 +971,27 @@ static int trunc_start(struct gfs2_inode *ip, u64 size) | |||
| 1039 | if (error) | 971 | if (error) |
| 1040 | goto out; | 972 | goto out; |
| 1041 | 973 | ||
| 974 | gfs2_trans_add_bh(ip->i_gl, dibh, 1); | ||
| 975 | |||
| 1042 | if (gfs2_is_stuffed(ip)) { | 976 | if (gfs2_is_stuffed(ip)) { |
| 1043 | u64 dsize = size + sizeof(struct gfs2_dinode); | 977 | gfs2_buffer_clear_tail(dibh, sizeof(struct gfs2_dinode) + newsize); |
| 1044 | ip->i_disksize = size; | ||
| 1045 | ip->i_inode.i_mtime = ip->i_inode.i_ctime = CURRENT_TIME; | ||
| 1046 | gfs2_trans_add_bh(ip->i_gl, dibh, 1); | ||
| 1047 | gfs2_dinode_out(ip, dibh->b_data); | ||
| 1048 | if (dsize > dibh->b_size) | ||
| 1049 | dsize = dibh->b_size; | ||
| 1050 | gfs2_buffer_clear_tail(dibh, dsize); | ||
| 1051 | error = 1; | ||
| 1052 | } else { | 978 | } else { |
| 1053 | if (size & (u64)(sdp->sd_sb.sb_bsize - 1)) | 979 | if (newsize & (u64)(sdp->sd_sb.sb_bsize - 1)) { |
| 1054 | error = gfs2_block_truncate_page(ip->i_inode.i_mapping); | 980 | error = gfs2_block_truncate_page(mapping, newsize); |
| 1055 | 981 | if (error) | |
| 1056 | if (!error) { | 982 | goto out_brelse; |
| 1057 | ip->i_disksize = size; | ||
| 1058 | ip->i_inode.i_mtime = ip->i_inode.i_ctime = CURRENT_TIME; | ||
| 1059 | ip->i_diskflags |= GFS2_DIF_TRUNC_IN_PROG; | ||
| 1060 | gfs2_trans_add_bh(ip->i_gl, dibh, 1); | ||
| 1061 | gfs2_dinode_out(ip, dibh->b_data); | ||
| 1062 | } | 983 | } |
| 984 | ip->i_diskflags |= GFS2_DIF_TRUNC_IN_PROG; | ||
| 1063 | } | 985 | } |
| 1064 | 986 | ||
| 1065 | brelse(dibh); | 987 | i_size_write(inode, newsize); |
| 988 | ip->i_disksize = newsize; | ||
| 989 | ip->i_inode.i_mtime = ip->i_inode.i_ctime = CURRENT_TIME; | ||
| 990 | gfs2_dinode_out(ip, dibh->b_data); | ||
| 1066 | 991 | ||
| 992 | truncate_pagecache(inode, oldsize, newsize); | ||
| 993 | out_brelse: | ||
| 994 | brelse(dibh); | ||
| 1067 | out: | 995 | out: |
| 1068 | gfs2_trans_end(sdp); | 996 | gfs2_trans_end(sdp); |
| 1069 | return error; | 997 | return error; |
| @@ -1143,86 +1071,149 @@ out: | |||
| 1143 | 1071 | ||
| 1144 | /** | 1072 | /** |
| 1145 | * do_shrink - make a file smaller | 1073 | * do_shrink - make a file smaller |
| 1146 | * @ip: the inode | 1074 | * @inode: the inode |
| 1147 | * @size: the size to make the file | 1075 | * @oldsize: the current inode size |
| 1148 | * @truncator: function to truncate the last partial block | 1076 | * @newsize: the size to make the file |
| 1149 | * | 1077 | * |
| 1150 | * Called with an exclusive lock on @ip. | 1078 | * Called with an exclusive lock on @inode. The @size must |
| 1079 | * be equal to or smaller than the current inode size. | ||
| 1151 | * | 1080 | * |
| 1152 | * Returns: errno | 1081 | * Returns: errno |
| 1153 | */ | 1082 | */ |
| 1154 | 1083 | ||
| 1155 | static int do_shrink(struct gfs2_inode *ip, u64 size) | 1084 | static int do_shrink(struct inode *inode, u64 oldsize, u64 newsize) |
| 1156 | { | 1085 | { |
| 1086 | struct gfs2_inode *ip = GFS2_I(inode); | ||
| 1157 | int error; | 1087 | int error; |
| 1158 | 1088 | ||
| 1159 | error = trunc_start(ip, size); | 1089 | error = trunc_start(inode, oldsize, newsize); |
| 1160 | if (error < 0) | 1090 | if (error < 0) |
| 1161 | return error; | 1091 | return error; |
| 1162 | if (error > 0) | 1092 | if (gfs2_is_stuffed(ip)) |
| 1163 | return 0; | 1093 | return 0; |
| 1164 | 1094 | ||
| 1165 | error = trunc_dealloc(ip, size); | 1095 | error = trunc_dealloc(ip, newsize); |
| 1166 | if (!error) | 1096 | if (error == 0) |
| 1167 | error = trunc_end(ip); | 1097 | error = trunc_end(ip); |
| 1168 | 1098 | ||
| 1169 | return error; | 1099 | return error; |
| 1170 | } | 1100 | } |
| 1171 | 1101 | ||
| 1172 | static int do_touch(struct gfs2_inode *ip, u64 size) | 1102 | void gfs2_trim_blocks(struct inode *inode) |
| 1173 | { | 1103 | { |
| 1174 | struct gfs2_sbd *sdp = GFS2_SB(&ip->i_inode); | 1104 | u64 size = inode->i_size; |
| 1105 | int ret; | ||
| 1106 | |||
| 1107 | ret = do_shrink(inode, size, size); | ||
| 1108 | WARN_ON(ret != 0); | ||
| 1109 | } | ||
| 1110 | |||
| 1111 | /** | ||
| 1112 | * do_grow - Touch and update inode size | ||
| 1113 | * @inode: The inode | ||
| 1114 | * @size: The new size | ||
| 1115 | * | ||
| 1116 | * This function updates the timestamps on the inode and | ||
| 1117 | * may also increase the size of the inode. This function | ||
| 1118 | * must not be called with @size any smaller than the current | ||
| 1119 | * inode size. | ||
| 1120 | * | ||
| 1121 | * Although it is not strictly required to unstuff files here, | ||
| 1122 | * earlier versions of GFS2 have a bug in the stuffed file reading | ||
| 1123 | * code which will result in a buffer overrun if the size is larger | ||
| 1124 | * than the max stuffed file size. In order to prevent this from | ||
| 1125 | * occuring, such files are unstuffed, but in other cases we can | ||
| 1126 | * just update the inode size directly. | ||
| 1127 | * | ||
| 1128 | * Returns: 0 on success, or -ve on error | ||
| 1129 | */ | ||
| 1130 | |||
| 1131 | static int do_grow(struct inode *inode, u64 size) | ||
| 1132 | { | ||
| 1133 | struct gfs2_inode *ip = GFS2_I(inode); | ||
| 1134 | struct gfs2_sbd *sdp = GFS2_SB(inode); | ||
| 1175 | struct buffer_head *dibh; | 1135 | struct buffer_head *dibh; |
| 1136 | struct gfs2_alloc *al = NULL; | ||
| 1176 | int error; | 1137 | int error; |
| 1177 | 1138 | ||
| 1178 | error = gfs2_trans_begin(sdp, RES_DINODE, 0); | 1139 | if (gfs2_is_stuffed(ip) && |
| 1140 | (size > (sdp->sd_sb.sb_bsize - sizeof(struct gfs2_dinode)))) { | ||
| 1141 | al = gfs2_alloc_get(ip); | ||
| 1142 | if (al == NULL) | ||
| 1143 | return -ENOMEM; | ||
| 1144 | |||
| 1145 | error = gfs2_quota_lock_check(ip); | ||
| 1146 | if (error) | ||
| 1147 | goto do_grow_alloc_put; | ||
| 1148 | |||
| 1149 | al->al_requested = 1; | ||
| 1150 | error = gfs2_inplace_reserve(ip); | ||
| 1151 | if (error) | ||
| 1152 | goto do_grow_qunlock; | ||
| 1153 | } | ||
| 1154 | |||
| 1155 | error = gfs2_trans_begin(sdp, RES_DINODE + 1, 0); | ||
| 1179 | if (error) | 1156 | if (error) |
| 1180 | return error; | 1157 | goto do_grow_release; |
| 1181 | 1158 | ||
| 1182 | down_write(&ip->i_rw_mutex); | 1159 | if (al) { |
| 1160 | error = gfs2_unstuff_dinode(ip, NULL); | ||
| 1161 | if (error) | ||
| 1162 | goto do_end_trans; | ||
| 1163 | } | ||
| 1183 | 1164 | ||
| 1184 | error = gfs2_meta_inode_buffer(ip, &dibh); | 1165 | error = gfs2_meta_inode_buffer(ip, &dibh); |
| 1185 | if (error) | 1166 | if (error) |
| 1186 | goto do_touch_out; | 1167 | goto do_end_trans; |
| 1187 | 1168 | ||
| 1169 | i_size_write(inode, size); | ||
| 1170 | ip->i_disksize = size; | ||
| 1188 | ip->i_inode.i_mtime = ip->i_inode.i_ctime = CURRENT_TIME; | 1171 | ip->i_inode.i_mtime = ip->i_inode.i_ctime = CURRENT_TIME; |
| 1189 | gfs2_trans_add_bh(ip->i_gl, dibh, 1); | 1172 | gfs2_trans_add_bh(ip->i_gl, dibh, 1); |
| 1190 | gfs2_dinode_out(ip, dibh->b_data); | 1173 | gfs2_dinode_out(ip, dibh->b_data); |
| 1191 | brelse(dibh); | 1174 | brelse(dibh); |
| 1192 | 1175 | ||
| 1193 | do_touch_out: | 1176 | do_end_trans: |
| 1194 | up_write(&ip->i_rw_mutex); | ||
| 1195 | gfs2_trans_end(sdp); | 1177 | gfs2_trans_end(sdp); |
| 1178 | do_grow_release: | ||
| 1179 | if (al) { | ||
| 1180 | gfs2_inplace_release(ip); | ||
| 1181 | do_grow_qunlock: | ||
| 1182 | gfs2_quota_unlock(ip); | ||
| 1183 | do_grow_alloc_put: | ||
| 1184 | gfs2_alloc_put(ip); | ||
| 1185 | } | ||
| 1196 | return error; | 1186 | return error; |
| 1197 | } | 1187 | } |
| 1198 | 1188 | ||
| 1199 | /** | 1189 | /** |
| 1200 | * gfs2_truncatei - make a file a given size | 1190 | * gfs2_setattr_size - make a file a given size |
| 1201 | * @ip: the inode | 1191 | * @inode: the inode |
| 1202 | * @size: the size to make the file | 1192 | * @newsize: the size to make the file |
| 1203 | * @truncator: function to truncate the last partial block | ||
| 1204 | * | 1193 | * |
| 1205 | * The file size can grow, shrink, or stay the same size. | 1194 | * The file size can grow, shrink, or stay the same size. This |
| 1195 | * is called holding i_mutex and an exclusive glock on the inode | ||
| 1196 | * in question. | ||
| 1206 | * | 1197 | * |
| 1207 | * Returns: errno | 1198 | * Returns: errno |
| 1208 | */ | 1199 | */ |
| 1209 | 1200 | ||
| 1210 | int gfs2_truncatei(struct gfs2_inode *ip, u64 size) | 1201 | int gfs2_setattr_size(struct inode *inode, u64 newsize) |
| 1211 | { | 1202 | { |
| 1212 | int error; | 1203 | int ret; |
| 1204 | u64 oldsize; | ||
| 1213 | 1205 | ||
| 1214 | if (gfs2_assert_warn(GFS2_SB(&ip->i_inode), S_ISREG(ip->i_inode.i_mode))) | 1206 | BUG_ON(!S_ISREG(inode->i_mode)); |
| 1215 | return -EINVAL; | ||
| 1216 | 1207 | ||
| 1217 | if (size > ip->i_disksize) | 1208 | ret = inode_newsize_ok(inode, newsize); |
| 1218 | error = do_grow(ip, size); | 1209 | if (ret) |
| 1219 | else if (size < ip->i_disksize) | 1210 | return ret; |
| 1220 | error = do_shrink(ip, size); | ||
| 1221 | else | ||
| 1222 | /* update time stamps */ | ||
| 1223 | error = do_touch(ip, size); | ||
| 1224 | 1211 | ||
| 1225 | return error; | 1212 | oldsize = inode->i_size; |
| 1213 | if (newsize >= oldsize) | ||
| 1214 | return do_grow(inode, newsize); | ||
| 1215 | |||
| 1216 | return do_shrink(inode, oldsize, newsize); | ||
| 1226 | } | 1217 | } |
| 1227 | 1218 | ||
| 1228 | int gfs2_truncatei_resume(struct gfs2_inode *ip) | 1219 | int gfs2_truncatei_resume(struct gfs2_inode *ip) |
diff --git a/fs/gfs2/bmap.h b/fs/gfs2/bmap.h index a20a5213135a..42fea03e2bd9 100644 --- a/fs/gfs2/bmap.h +++ b/fs/gfs2/bmap.h | |||
| @@ -44,14 +44,16 @@ static inline void gfs2_write_calc_reserv(const struct gfs2_inode *ip, | |||
| 44 | } | 44 | } |
| 45 | } | 45 | } |
| 46 | 46 | ||
| 47 | int gfs2_unstuff_dinode(struct gfs2_inode *ip, struct page *page); | 47 | extern int gfs2_unstuff_dinode(struct gfs2_inode *ip, struct page *page); |
| 48 | int gfs2_block_map(struct inode *inode, sector_t lblock, struct buffer_head *bh, int create); | 48 | extern int gfs2_block_map(struct inode *inode, sector_t lblock, |
| 49 | int gfs2_extent_map(struct inode *inode, u64 lblock, int *new, u64 *dblock, unsigned *extlen); | 49 | struct buffer_head *bh, int create); |
| 50 | 50 | extern int gfs2_extent_map(struct inode *inode, u64 lblock, int *new, | |
| 51 | int gfs2_truncatei(struct gfs2_inode *ip, u64 size); | 51 | u64 *dblock, unsigned *extlen); |
| 52 | int gfs2_truncatei_resume(struct gfs2_inode *ip); | 52 | extern int gfs2_setattr_size(struct inode *inode, u64 size); |
| 53 | int gfs2_file_dealloc(struct gfs2_inode *ip); | 53 | extern void gfs2_trim_blocks(struct inode *inode); |
| 54 | int gfs2_write_alloc_required(struct gfs2_inode *ip, u64 offset, | 54 | extern int gfs2_truncatei_resume(struct gfs2_inode *ip); |
| 55 | unsigned int len); | 55 | extern int gfs2_file_dealloc(struct gfs2_inode *ip); |
| 56 | extern int gfs2_write_alloc_required(struct gfs2_inode *ip, u64 offset, | ||
| 57 | unsigned int len); | ||
| 56 | 58 | ||
| 57 | #endif /* __BMAP_DOT_H__ */ | 59 | #endif /* __BMAP_DOT_H__ */ |
diff --git a/fs/gfs2/ops_inode.c b/fs/gfs2/ops_inode.c index 1009be2c9737..1d3f2fb466bd 100644 --- a/fs/gfs2/ops_inode.c +++ b/fs/gfs2/ops_inode.c | |||
| @@ -1071,30 +1071,6 @@ int gfs2_permission(struct inode *inode, int mask) | |||
| 1071 | return error; | 1071 | return error; |
| 1072 | } | 1072 | } |
| 1073 | 1073 | ||
| 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) | 1074 | static int setattr_chown(struct inode *inode, struct iattr *attr) |
| 1099 | { | 1075 | { |
| 1100 | struct gfs2_inode *ip = GFS2_I(inode); | 1076 | struct gfs2_inode *ip = GFS2_I(inode); |
| @@ -1195,7 +1171,7 @@ static int gfs2_setattr(struct dentry *dentry, struct iattr *attr) | |||
| 1195 | goto out; | 1171 | goto out; |
| 1196 | 1172 | ||
| 1197 | if (attr->ia_valid & ATTR_SIZE) | 1173 | if (attr->ia_valid & ATTR_SIZE) |
| 1198 | error = setattr_size(inode, attr); | 1174 | error = gfs2_setattr_size(inode, attr->ia_size); |
| 1199 | else if (attr->ia_valid & (ATTR_UID | ATTR_GID)) | 1175 | else if (attr->ia_valid & (ATTR_UID | ATTR_GID)) |
| 1200 | error = setattr_chown(inode, attr); | 1176 | error = setattr_chown(inode, attr); |
| 1201 | else if ((attr->ia_valid & ATTR_MODE) && IS_POSIXACL(inode)) | 1177 | else if ((attr->ia_valid & ATTR_MODE) && IS_POSIXACL(inode)) |
