aboutsummaryrefslogtreecommitdiffstats
path: root/fs/gfs2/bmap.c
diff options
context:
space:
mode:
Diffstat (limited to 'fs/gfs2/bmap.c')
-rw-r--r--fs/gfs2/bmap.c288
1 files changed, 147 insertions, 141 deletions
diff --git a/fs/gfs2/bmap.c b/fs/gfs2/bmap.c
index 6f482809d1a3..e65493a8ac00 100644
--- a/fs/gfs2/bmap.c
+++ b/fs/gfs2/bmap.c
@@ -21,6 +21,7 @@
21#include "meta_io.h" 21#include "meta_io.h"
22#include "quota.h" 22#include "quota.h"
23#include "rgrp.h" 23#include "rgrp.h"
24#include "super.h"
24#include "trans.h" 25#include "trans.h"
25#include "dir.h" 26#include "dir.h"
26#include "util.h" 27#include "util.h"
@@ -50,7 +51,7 @@ struct strip_mine {
50 * @ip: the inode 51 * @ip: the inode
51 * @dibh: the dinode buffer 52 * @dibh: the dinode buffer
52 * @block: the block number that was allocated 53 * @block: the block number that was allocated
53 * @private: any locked page held by the caller process 54 * @page: The (optional) page. This is looked up if @page is NULL
54 * 55 *
55 * Returns: errno 56 * Returns: errno
56 */ 57 */
@@ -109,8 +110,7 @@ static int gfs2_unstuffer_page(struct gfs2_inode *ip, struct buffer_head *dibh,
109/** 110/**
110 * gfs2_unstuff_dinode - Unstuff a dinode when the data has grown too big 111 * gfs2_unstuff_dinode - Unstuff a dinode when the data has grown too big
111 * @ip: The GFS2 inode to unstuff 112 * @ip: The GFS2 inode to unstuff
112 * @unstuffer: the routine that handles unstuffing a non-zero length file 113 * @page: The (optional) page. This is looked up if the @page is NULL
113 * @private: private data for the unstuffer
114 * 114 *
115 * This routine unstuffs a dinode and returns it to a "normal" state such 115 * This routine unstuffs a dinode and returns it to a "normal" state such
116 * that the height can be grown in the traditional way. 116 * that the height can be grown in the traditional way.
@@ -132,7 +132,7 @@ int gfs2_unstuff_dinode(struct gfs2_inode *ip, struct page *page)
132 if (error) 132 if (error)
133 goto out; 133 goto out;
134 134
135 if (ip->i_disksize) { 135 if (i_size_read(&ip->i_inode)) {
136 /* Get a free block, fill it with the stuffed data, 136 /* Get a free block, fill it with the stuffed data,
137 and write it out to disk */ 137 and write it out to disk */
138 138
@@ -161,7 +161,7 @@ int gfs2_unstuff_dinode(struct gfs2_inode *ip, struct page *page)
161 di = (struct gfs2_dinode *)dibh->b_data; 161 di = (struct gfs2_dinode *)dibh->b_data;
162 gfs2_buffer_clear_tail(dibh, sizeof(struct gfs2_dinode)); 162 gfs2_buffer_clear_tail(dibh, sizeof(struct gfs2_dinode));
163 163
164 if (ip->i_disksize) { 164 if (i_size_read(&ip->i_inode)) {
165 *(__be64 *)(di + 1) = cpu_to_be64(block); 165 *(__be64 *)(di + 1) = cpu_to_be64(block);
166 gfs2_add_inode_blocks(&ip->i_inode, 1); 166 gfs2_add_inode_blocks(&ip->i_inode, 1);
167 di->di_blocks = cpu_to_be64(gfs2_get_inode_blocks(&ip->i_inode)); 167 di->di_blocks = cpu_to_be64(gfs2_get_inode_blocks(&ip->i_inode));
@@ -758,13 +758,13 @@ static int do_strip(struct gfs2_inode *ip, struct buffer_head *dibh,
758 struct gfs2_sbd *sdp = GFS2_SB(&ip->i_inode); 758 struct gfs2_sbd *sdp = GFS2_SB(&ip->i_inode);
759 struct gfs2_rgrp_list rlist; 759 struct gfs2_rgrp_list rlist;
760 u64 bn, bstart; 760 u64 bn, bstart;
761 u32 blen; 761 u32 blen, btotal;
762 __be64 *p; 762 __be64 *p;
763 unsigned int rg_blocks = 0; 763 unsigned int rg_blocks = 0;
764 int metadata; 764 int metadata;
765 unsigned int revokes = 0; 765 unsigned int revokes = 0;
766 int x; 766 int x;
767 int error; 767 int error = 0;
768 768
769 if (!*top) 769 if (!*top)
770 sm->sm_first = 0; 770 sm->sm_first = 0;
@@ -780,8 +780,14 @@ static int do_strip(struct gfs2_inode *ip, struct buffer_head *dibh,
780 metadata = (height != ip->i_height - 1); 780 metadata = (height != ip->i_height - 1);
781 if (metadata) 781 if (metadata)
782 revokes = (height) ? sdp->sd_inptrs : sdp->sd_diptrs; 782 revokes = (height) ? sdp->sd_inptrs : sdp->sd_diptrs;
783 else if (ip->i_depth)
784 revokes = sdp->sd_inptrs;
785
786 if (ip != GFS2_I(sdp->sd_rindex))
787 error = gfs2_rindex_hold(sdp, &ip->i_alloc->al_ri_gh);
788 else if (!sdp->sd_rgrps)
789 error = gfs2_ri_update(ip);
783 790
784 error = gfs2_rindex_hold(sdp, &ip->i_alloc->al_ri_gh);
785 if (error) 791 if (error)
786 return error; 792 return error;
787 793
@@ -836,6 +842,7 @@ static int do_strip(struct gfs2_inode *ip, struct buffer_head *dibh,
836 842
837 bstart = 0; 843 bstart = 0;
838 blen = 0; 844 blen = 0;
845 btotal = 0;
839 846
840 for (p = top; p < bottom; p++) { 847 for (p = top; p < bottom; p++) {
841 if (!*p) 848 if (!*p)
@@ -848,9 +855,11 @@ static int do_strip(struct gfs2_inode *ip, struct buffer_head *dibh,
848 else { 855 else {
849 if (bstart) { 856 if (bstart) {
850 if (metadata) 857 if (metadata)
851 gfs2_free_meta(ip, bstart, blen); 858 __gfs2_free_meta(ip, bstart, blen);
852 else 859 else
853 gfs2_free_data(ip, bstart, blen); 860 __gfs2_free_data(ip, bstart, blen);
861
862 btotal += blen;
854 } 863 }
855 864
856 bstart = bn; 865 bstart = bn;
@@ -862,11 +871,17 @@ static int do_strip(struct gfs2_inode *ip, struct buffer_head *dibh,
862 } 871 }
863 if (bstart) { 872 if (bstart) {
864 if (metadata) 873 if (metadata)
865 gfs2_free_meta(ip, bstart, blen); 874 __gfs2_free_meta(ip, bstart, blen);
866 else 875 else
867 gfs2_free_data(ip, bstart, blen); 876 __gfs2_free_data(ip, bstart, blen);
877
878 btotal += blen;
868 } 879 }
869 880
881 gfs2_statfs_change(sdp, 0, +btotal, 0);
882 gfs2_quota_change(ip, -(s64)btotal, ip->i_inode.i_uid,
883 ip->i_inode.i_gid);
884
870 ip->i_inode.i_mtime = ip->i_inode.i_ctime = CURRENT_TIME; 885 ip->i_inode.i_mtime = ip->i_inode.i_ctime = CURRENT_TIME;
871 886
872 gfs2_dinode_out(ip, dibh->b_data); 887 gfs2_dinode_out(ip, dibh->b_data);
@@ -880,88 +895,20 @@ out_rg_gunlock:
880out_rlist: 895out_rlist:
881 gfs2_rlist_free(&rlist); 896 gfs2_rlist_free(&rlist);
882out: 897out:
883 gfs2_glock_dq_uninit(&ip->i_alloc->al_ri_gh); 898 if (ip != GFS2_I(sdp->sd_rindex))
884 return error; 899 gfs2_glock_dq_uninit(&ip->i_alloc->al_ri_gh);
885}
886
887/**
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
897static 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
941out_brelse:
942 brelse(dibh);
943out_end_trans:
944 gfs2_trans_end(sdp);
945out_ipres:
946 gfs2_inplace_release(ip);
947out_gunlock_q:
948 gfs2_quota_unlock(ip);
949out:
950 gfs2_alloc_put(ip);
951 return error; 900 return error;
952} 901}
953 902
954
955/** 903/**
956 * gfs2_block_truncate_page - Deal with zeroing out data for truncate 904 * gfs2_block_truncate_page - Deal with zeroing out data for truncate
957 * 905 *
958 * This is partly borrowed from ext3. 906 * This is partly borrowed from ext3.
959 */ 907 */
960static int gfs2_block_truncate_page(struct address_space *mapping) 908static int gfs2_block_truncate_page(struct address_space *mapping, loff_t from)
961{ 909{
962 struct inode *inode = mapping->host; 910 struct inode *inode = mapping->host;
963 struct gfs2_inode *ip = GFS2_I(inode); 911 struct gfs2_inode *ip = GFS2_I(inode);
964 loff_t from = inode->i_size;
965 unsigned long index = from >> PAGE_CACHE_SHIFT; 912 unsigned long index = from >> PAGE_CACHE_SHIFT;
966 unsigned offset = from & (PAGE_CACHE_SIZE-1); 913 unsigned offset = from & (PAGE_CACHE_SIZE-1);
967 unsigned blocksize, iblock, length, pos; 914 unsigned blocksize, iblock, length, pos;
@@ -1023,9 +970,11 @@ unlock:
1023 return err; 970 return err;
1024} 971}
1025 972
1026static int trunc_start(struct gfs2_inode *ip, u64 size) 973static int trunc_start(struct inode *inode, u64 oldsize, u64 newsize)
1027{ 974{
1028 struct gfs2_sbd *sdp = GFS2_SB(&ip->i_inode); 975 struct gfs2_inode *ip = GFS2_I(inode);
976 struct gfs2_sbd *sdp = GFS2_SB(inode);
977 struct address_space *mapping = inode->i_mapping;
1029 struct buffer_head *dibh; 978 struct buffer_head *dibh;
1030 int journaled = gfs2_is_jdata(ip); 979 int journaled = gfs2_is_jdata(ip);
1031 int error; 980 int error;
@@ -1039,31 +988,26 @@ static int trunc_start(struct gfs2_inode *ip, u64 size)
1039 if (error) 988 if (error)
1040 goto out; 989 goto out;
1041 990
991 gfs2_trans_add_bh(ip->i_gl, dibh, 1);
992
1042 if (gfs2_is_stuffed(ip)) { 993 if (gfs2_is_stuffed(ip)) {
1043 u64 dsize = size + sizeof(struct gfs2_dinode); 994 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 { 995 } else {
1053 if (size & (u64)(sdp->sd_sb.sb_bsize - 1)) 996 if (newsize & (u64)(sdp->sd_sb.sb_bsize - 1)) {
1054 error = gfs2_block_truncate_page(ip->i_inode.i_mapping); 997 error = gfs2_block_truncate_page(mapping, newsize);
1055 998 if (error)
1056 if (!error) { 999 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 } 1000 }
1001 ip->i_diskflags |= GFS2_DIF_TRUNC_IN_PROG;
1063 } 1002 }
1064 1003
1065 brelse(dibh); 1004 i_size_write(inode, newsize);
1005 ip->i_inode.i_mtime = ip->i_inode.i_ctime = CURRENT_TIME;
1006 gfs2_dinode_out(ip, dibh->b_data);
1066 1007
1008 truncate_pagecache(inode, oldsize, newsize);
1009out_brelse:
1010 brelse(dibh);
1067out: 1011out:
1068 gfs2_trans_end(sdp); 1012 gfs2_trans_end(sdp);
1069 return error; 1013 return error;
@@ -1123,7 +1067,7 @@ static int trunc_end(struct gfs2_inode *ip)
1123 if (error) 1067 if (error)
1124 goto out; 1068 goto out;
1125 1069
1126 if (!ip->i_disksize) { 1070 if (!i_size_read(&ip->i_inode)) {
1127 ip->i_height = 0; 1071 ip->i_height = 0;
1128 ip->i_goal = ip->i_no_addr; 1072 ip->i_goal = ip->i_no_addr;
1129 gfs2_buffer_clear_tail(dibh, sizeof(struct gfs2_dinode)); 1073 gfs2_buffer_clear_tail(dibh, sizeof(struct gfs2_dinode));
@@ -1143,92 +1087,154 @@ out:
1143 1087
1144/** 1088/**
1145 * do_shrink - make a file smaller 1089 * do_shrink - make a file smaller
1146 * @ip: the inode 1090 * @inode: the inode
1147 * @size: the size to make the file 1091 * @oldsize: the current inode size
1148 * @truncator: function to truncate the last partial block 1092 * @newsize: the size to make the file
1149 * 1093 *
1150 * Called with an exclusive lock on @ip. 1094 * Called with an exclusive lock on @inode. The @size must
1095 * be equal to or smaller than the current inode size.
1151 * 1096 *
1152 * Returns: errno 1097 * Returns: errno
1153 */ 1098 */
1154 1099
1155static int do_shrink(struct gfs2_inode *ip, u64 size) 1100static int do_shrink(struct inode *inode, u64 oldsize, u64 newsize)
1156{ 1101{
1102 struct gfs2_inode *ip = GFS2_I(inode);
1157 int error; 1103 int error;
1158 1104
1159 error = trunc_start(ip, size); 1105 error = trunc_start(inode, oldsize, newsize);
1160 if (error < 0) 1106 if (error < 0)
1161 return error; 1107 return error;
1162 if (error > 0) 1108 if (gfs2_is_stuffed(ip))
1163 return 0; 1109 return 0;
1164 1110
1165 error = trunc_dealloc(ip, size); 1111 error = trunc_dealloc(ip, newsize);
1166 if (!error) 1112 if (error == 0)
1167 error = trunc_end(ip); 1113 error = trunc_end(ip);
1168 1114
1169 return error; 1115 return error;
1170} 1116}
1171 1117
1172static int do_touch(struct gfs2_inode *ip, u64 size) 1118void gfs2_trim_blocks(struct inode *inode)
1173{ 1119{
1174 struct gfs2_sbd *sdp = GFS2_SB(&ip->i_inode); 1120 u64 size = inode->i_size;
1121 int ret;
1122
1123 ret = do_shrink(inode, size, size);
1124 WARN_ON(ret != 0);
1125}
1126
1127/**
1128 * do_grow - Touch and update inode size
1129 * @inode: The inode
1130 * @size: The new size
1131 *
1132 * This function updates the timestamps on the inode and
1133 * may also increase the size of the inode. This function
1134 * must not be called with @size any smaller than the current
1135 * inode size.
1136 *
1137 * Although it is not strictly required to unstuff files here,
1138 * earlier versions of GFS2 have a bug in the stuffed file reading
1139 * code which will result in a buffer overrun if the size is larger
1140 * than the max stuffed file size. In order to prevent this from
1141 * occurring, such files are unstuffed, but in other cases we can
1142 * just update the inode size directly.
1143 *
1144 * Returns: 0 on success, or -ve on error
1145 */
1146
1147static int do_grow(struct inode *inode, u64 size)
1148{
1149 struct gfs2_inode *ip = GFS2_I(inode);
1150 struct gfs2_sbd *sdp = GFS2_SB(inode);
1175 struct buffer_head *dibh; 1151 struct buffer_head *dibh;
1152 struct gfs2_alloc *al = NULL;
1176 int error; 1153 int error;
1177 1154
1178 error = gfs2_trans_begin(sdp, RES_DINODE, 0); 1155 if (gfs2_is_stuffed(ip) &&
1156 (size > (sdp->sd_sb.sb_bsize - sizeof(struct gfs2_dinode)))) {
1157 al = gfs2_alloc_get(ip);
1158 if (al == NULL)
1159 return -ENOMEM;
1160
1161 error = gfs2_quota_lock_check(ip);
1162 if (error)
1163 goto do_grow_alloc_put;
1164
1165 al->al_requested = 1;
1166 error = gfs2_inplace_reserve(ip);
1167 if (error)
1168 goto do_grow_qunlock;
1169 }
1170
1171 error = gfs2_trans_begin(sdp, RES_DINODE + RES_STATFS + RES_RG_BIT, 0);
1179 if (error) 1172 if (error)
1180 return error; 1173 goto do_grow_release;
1181 1174
1182 down_write(&ip->i_rw_mutex); 1175 if (al) {
1176 error = gfs2_unstuff_dinode(ip, NULL);
1177 if (error)
1178 goto do_end_trans;
1179 }
1183 1180
1184 error = gfs2_meta_inode_buffer(ip, &dibh); 1181 error = gfs2_meta_inode_buffer(ip, &dibh);
1185 if (error) 1182 if (error)
1186 goto do_touch_out; 1183 goto do_end_trans;
1187 1184
1185 i_size_write(inode, size);
1188 ip->i_inode.i_mtime = ip->i_inode.i_ctime = CURRENT_TIME; 1186 ip->i_inode.i_mtime = ip->i_inode.i_ctime = CURRENT_TIME;
1189 gfs2_trans_add_bh(ip->i_gl, dibh, 1); 1187 gfs2_trans_add_bh(ip->i_gl, dibh, 1);
1190 gfs2_dinode_out(ip, dibh->b_data); 1188 gfs2_dinode_out(ip, dibh->b_data);
1191 brelse(dibh); 1189 brelse(dibh);
1192 1190
1193do_touch_out: 1191do_end_trans:
1194 up_write(&ip->i_rw_mutex);
1195 gfs2_trans_end(sdp); 1192 gfs2_trans_end(sdp);
1193do_grow_release:
1194 if (al) {
1195 gfs2_inplace_release(ip);
1196do_grow_qunlock:
1197 gfs2_quota_unlock(ip);
1198do_grow_alloc_put:
1199 gfs2_alloc_put(ip);
1200 }
1196 return error; 1201 return error;
1197} 1202}
1198 1203
1199/** 1204/**
1200 * gfs2_truncatei - make a file a given size 1205 * gfs2_setattr_size - make a file a given size
1201 * @ip: the inode 1206 * @inode: the inode
1202 * @size: the size to make the file 1207 * @newsize: the size to make the file
1203 * @truncator: function to truncate the last partial block
1204 * 1208 *
1205 * The file size can grow, shrink, or stay the same size. 1209 * The file size can grow, shrink, or stay the same size. This
1210 * is called holding i_mutex and an exclusive glock on the inode
1211 * in question.
1206 * 1212 *
1207 * Returns: errno 1213 * Returns: errno
1208 */ 1214 */
1209 1215
1210int gfs2_truncatei(struct gfs2_inode *ip, u64 size) 1216int gfs2_setattr_size(struct inode *inode, u64 newsize)
1211{ 1217{
1212 int error; 1218 int ret;
1219 u64 oldsize;
1213 1220
1214 if (gfs2_assert_warn(GFS2_SB(&ip->i_inode), S_ISREG(ip->i_inode.i_mode))) 1221 BUG_ON(!S_ISREG(inode->i_mode));
1215 return -EINVAL;
1216 1222
1217 if (size > ip->i_disksize) 1223 ret = inode_newsize_ok(inode, newsize);
1218 error = do_grow(ip, size); 1224 if (ret)
1219 else if (size < ip->i_disksize) 1225 return ret;
1220 error = do_shrink(ip, size);
1221 else
1222 /* update time stamps */
1223 error = do_touch(ip, size);
1224 1226
1225 return error; 1227 oldsize = inode->i_size;
1228 if (newsize >= oldsize)
1229 return do_grow(inode, newsize);
1230
1231 return do_shrink(inode, oldsize, newsize);
1226} 1232}
1227 1233
1228int gfs2_truncatei_resume(struct gfs2_inode *ip) 1234int gfs2_truncatei_resume(struct gfs2_inode *ip)
1229{ 1235{
1230 int error; 1236 int error;
1231 error = trunc_dealloc(ip, ip->i_disksize); 1237 error = trunc_dealloc(ip, i_size_read(&ip->i_inode));
1232 if (!error) 1238 if (!error)
1233 error = trunc_end(ip); 1239 error = trunc_end(ip);
1234 return error; 1240 return error;
@@ -1269,7 +1275,7 @@ int gfs2_write_alloc_required(struct gfs2_inode *ip, u64 offset,
1269 1275
1270 shift = sdp->sd_sb.sb_bsize_shift; 1276 shift = sdp->sd_sb.sb_bsize_shift;
1271 BUG_ON(gfs2_is_dir(ip)); 1277 BUG_ON(gfs2_is_dir(ip));
1272 end_of_file = (ip->i_disksize + sdp->sd_sb.sb_bsize - 1) >> shift; 1278 end_of_file = (i_size_read(&ip->i_inode) + sdp->sd_sb.sb_bsize - 1) >> shift;
1273 lblock = offset >> shift; 1279 lblock = offset >> shift;
1274 lblock_stop = (offset + len + sdp->sd_sb.sb_bsize - 1) >> shift; 1280 lblock_stop = (offset + len + sdp->sd_sb.sb_bsize - 1) >> shift;
1275 if (lblock_stop > end_of_file) 1281 if (lblock_stop > end_of_file)