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.c108
1 files changed, 37 insertions, 71 deletions
diff --git a/fs/gfs2/bmap.c b/fs/gfs2/bmap.c
index a25444ac648b..5a3187049dd7 100644
--- a/fs/gfs2/bmap.c
+++ b/fs/gfs2/bmap.c
@@ -166,7 +166,7 @@ int gfs2_unstuff_dinode(struct gfs2_inode *ip, struct page *page)
166 di->di_blocks = cpu_to_be64(ip->i_di.di_blocks); 166 di->di_blocks = cpu_to_be64(ip->i_di.di_blocks);
167 } 167 }
168 168
169 ip->i_di.di_height = 1; 169 ip->i_height = 1;
170 di->di_height = cpu_to_be16(1); 170 di->di_height = cpu_to_be16(1);
171 171
172out_brelse: 172out_brelse:
@@ -177,43 +177,6 @@ out:
177} 177}
178 178
179/** 179/**
180 * calc_tree_height - Calculate the height of a metadata tree
181 * @ip: The GFS2 inode
182 * @size: The proposed size of the file
183 *
184 * Work out how tall a metadata tree needs to be in order to accommodate a
185 * file of a particular size. If size is less than the current size of
186 * the inode, then the current size of the inode is used instead of the
187 * supplied one.
188 *
189 * Returns: the height the tree should be
190 */
191
192static unsigned int calc_tree_height(struct gfs2_inode *ip, u64 size)
193{
194 struct gfs2_sbd *sdp = GFS2_SB(&ip->i_inode);
195 u64 *arr;
196 unsigned int max, height;
197
198 if (ip->i_di.di_size > size)
199 size = ip->i_di.di_size;
200
201 if (gfs2_is_dir(ip)) {
202 arr = sdp->sd_jheightsize;
203 max = sdp->sd_max_jheight;
204 } else {
205 arr = sdp->sd_heightsize;
206 max = sdp->sd_max_height;
207 }
208
209 for (height = 0; height < max; height++)
210 if (arr[height] >= size)
211 break;
212
213 return height;
214}
215
216/**
217 * build_height - Build a metadata tree of the requested height 180 * build_height - Build a metadata tree of the requested height
218 * @ip: The GFS2 inode 181 * @ip: The GFS2 inode
219 * @height: The height to build to 182 * @height: The height to build to
@@ -225,7 +188,7 @@ static unsigned int calc_tree_height(struct gfs2_inode *ip, u64 size)
225static int build_height(struct inode *inode, unsigned height) 188static int build_height(struct inode *inode, unsigned height)
226{ 189{
227 struct gfs2_inode *ip = GFS2_I(inode); 190 struct gfs2_inode *ip = GFS2_I(inode);
228 unsigned new_height = height - ip->i_di.di_height; 191 unsigned new_height = height - ip->i_height;
229 struct buffer_head *dibh; 192 struct buffer_head *dibh;
230 struct buffer_head *blocks[GFS2_MAX_META_HEIGHT]; 193 struct buffer_head *blocks[GFS2_MAX_META_HEIGHT];
231 struct gfs2_dinode *di; 194 struct gfs2_dinode *di;
@@ -234,7 +197,7 @@ static int build_height(struct inode *inode, unsigned height)
234 u64 bn; 197 u64 bn;
235 unsigned n; 198 unsigned n;
236 199
237 if (height <= ip->i_di.di_height) 200 if (height <= ip->i_height)
238 return 0; 201 return 0;
239 202
240 error = gfs2_meta_inode_buffer(ip, &dibh); 203 error = gfs2_meta_inode_buffer(ip, &dibh);
@@ -270,10 +233,10 @@ static int build_height(struct inode *inode, unsigned height)
270 di = (struct gfs2_dinode *)dibh->b_data; 233 di = (struct gfs2_dinode *)dibh->b_data;
271 gfs2_buffer_clear_tail(dibh, sizeof(struct gfs2_dinode)); 234 gfs2_buffer_clear_tail(dibh, sizeof(struct gfs2_dinode));
272 *(__be64 *)(di + 1) = cpu_to_be64(bn); 235 *(__be64 *)(di + 1) = cpu_to_be64(bn);
273 ip->i_di.di_height += new_height; 236 ip->i_height += new_height;
274 ip->i_di.di_blocks += new_height; 237 ip->i_di.di_blocks += new_height;
275 gfs2_set_inode_blocks(&ip->i_inode); 238 gfs2_set_inode_blocks(&ip->i_inode);
276 di->di_height = cpu_to_be16(ip->i_di.di_height); 239 di->di_height = cpu_to_be16(ip->i_height);
277 di->di_blocks = cpu_to_be64(ip->i_di.di_blocks); 240 di->di_blocks = cpu_to_be64(ip->i_di.di_blocks);
278 brelse(dibh); 241 brelse(dibh);
279 return error; 242 return error;
@@ -345,7 +308,7 @@ static void find_metapath(struct gfs2_inode *ip, u64 block,
345 u64 b = block; 308 u64 b = block;
346 unsigned int i; 309 unsigned int i;
347 310
348 for (i = ip->i_di.di_height; i--;) 311 for (i = ip->i_height; i--;)
349 mp->mp_list[i] = do_div(b, sdp->sd_inptrs); 312 mp->mp_list[i] = do_div(b, sdp->sd_inptrs);
350 313
351} 314}
@@ -407,7 +370,7 @@ static int lookup_block(struct gfs2_inode *ip, struct buffer_head *bh,
407 if (!create) 370 if (!create)
408 return 0; 371 return 0;
409 372
410 if (height == ip->i_di.di_height - 1 && !gfs2_is_dir(ip)) 373 if (height == ip->i_height - 1 && !gfs2_is_dir(ip))
411 *block = gfs2_alloc_data(ip); 374 *block = gfs2_alloc_data(ip);
412 else 375 else
413 *block = gfs2_alloc_meta(ip); 376 *block = gfs2_alloc_meta(ip);
@@ -458,8 +421,7 @@ int gfs2_block_map(struct inode *inode, sector_t lblock,
458 struct gfs2_inode *ip = GFS2_I(inode); 421 struct gfs2_inode *ip = GFS2_I(inode);
459 struct gfs2_sbd *sdp = GFS2_SB(inode); 422 struct gfs2_sbd *sdp = GFS2_SB(inode);
460 struct buffer_head *bh; 423 struct buffer_head *bh;
461 unsigned int bsize; 424 unsigned int bsize = sdp->sd_sb.sb_bsize;
462 unsigned int height;
463 unsigned int end_of_metadata; 425 unsigned int end_of_metadata;
464 unsigned int x; 426 unsigned int x;
465 int error = 0; 427 int error = 0;
@@ -470,7 +432,7 @@ int gfs2_block_map(struct inode *inode, sector_t lblock,
470 struct metapath mp; 432 struct metapath mp;
471 u64 size; 433 u64 size;
472 struct buffer_head *dibh = NULL; 434 struct buffer_head *dibh = NULL;
473 435 const u64 *arr = sdp->sd_heightsize;
474 BUG_ON(maxlen == 0); 436 BUG_ON(maxlen == 0);
475 437
476 if (gfs2_assert_warn(sdp, !gfs2_is_stuffed(ip))) 438 if (gfs2_assert_warn(sdp, !gfs2_is_stuffed(ip)))
@@ -480,23 +442,25 @@ int gfs2_block_map(struct inode *inode, sector_t lblock,
480 clear_buffer_mapped(bh_map); 442 clear_buffer_mapped(bh_map);
481 clear_buffer_new(bh_map); 443 clear_buffer_new(bh_map);
482 clear_buffer_boundary(bh_map); 444 clear_buffer_boundary(bh_map);
483 bsize = gfs2_is_dir(ip) ? sdp->sd_jbsize : sdp->sd_sb.sb_bsize; 445 if (gfs2_is_dir(ip)) {
446 bsize = sdp->sd_jbsize;
447 arr = sdp->sd_jheightsize;
448 }
484 size = (lblock + 1) * bsize; 449 size = (lblock + 1) * bsize;
485 450
486 if (size > ip->i_di.di_size) { 451 if (size > arr[ip->i_height]) {
487 height = calc_tree_height(ip, size); 452 u8 height = ip->i_height;
488 if (ip->i_di.di_height < height) { 453 if (!create)
489 if (!create) 454 goto out_ok;
490 goto out_ok; 455 while (size > arr[height])
491 456 height++;
492 error = build_height(inode, height); 457 error = build_height(inode, height);
493 if (error) 458 if (error)
494 goto out_fail; 459 goto out_fail;
495 }
496 } 460 }
497 461
498 find_metapath(ip, lblock, &mp); 462 find_metapath(ip, lblock, &mp);
499 end_of_metadata = ip->i_di.di_height - 1; 463 end_of_metadata = ip->i_height - 1;
500 error = gfs2_meta_inode_buffer(ip, &bh); 464 error = gfs2_meta_inode_buffer(ip, &bh);
501 if (error) 465 if (error)
502 goto out_fail; 466 goto out_fail;
@@ -624,7 +588,7 @@ static int recursive_scan(struct gfs2_inode *ip, struct buffer_head *dibh,
624 if (error) 588 if (error)
625 goto out; 589 goto out;
626 590
627 if (height < ip->i_di.di_height - 1) 591 if (height < ip->i_height - 1)
628 for (; top < bottom; top++, first = 0) { 592 for (; top < bottom; top++, first = 0) {
629 if (!*top) 593 if (!*top)
630 continue; 594 continue;
@@ -682,7 +646,7 @@ static int do_strip(struct gfs2_inode *ip, struct buffer_head *dibh,
682 sm->sm_first = 0; 646 sm->sm_first = 0;
683 } 647 }
684 648
685 metadata = (height != ip->i_di.di_height - 1); 649 metadata = (height != ip->i_height - 1);
686 if (metadata) 650 if (metadata)
687 revokes = (height) ? sdp->sd_inptrs : sdp->sd_diptrs; 651 revokes = (height) ? sdp->sd_inptrs : sdp->sd_diptrs;
688 652
@@ -807,7 +771,6 @@ static int do_grow(struct gfs2_inode *ip, u64 size)
807 struct gfs2_sbd *sdp = GFS2_SB(&ip->i_inode); 771 struct gfs2_sbd *sdp = GFS2_SB(&ip->i_inode);
808 struct gfs2_alloc *al; 772 struct gfs2_alloc *al;
809 struct buffer_head *dibh; 773 struct buffer_head *dibh;
810 unsigned int h;
811 int error; 774 int error;
812 775
813 al = gfs2_alloc_get(ip); 776 al = gfs2_alloc_get(ip);
@@ -833,20 +796,23 @@ static int do_grow(struct gfs2_inode *ip, u64 size)
833 goto out_ipres; 796 goto out_ipres;
834 797
835 if (size > sdp->sd_sb.sb_bsize - sizeof(struct gfs2_dinode)) { 798 if (size > sdp->sd_sb.sb_bsize - sizeof(struct gfs2_dinode)) {
799 const u64 *arr = sdp->sd_heightsize;
836 if (gfs2_is_stuffed(ip)) { 800 if (gfs2_is_stuffed(ip)) {
837 error = gfs2_unstuff_dinode(ip, NULL); 801 error = gfs2_unstuff_dinode(ip, NULL);
838 if (error) 802 if (error)
839 goto out_end_trans; 803 goto out_end_trans;
840 } 804 }
841 805
842 h = calc_tree_height(ip, size); 806 down_write(&ip->i_rw_mutex);
843 if (ip->i_di.di_height < h) { 807 if (size > arr[ip->i_height]) {
844 down_write(&ip->i_rw_mutex); 808 u8 height = ip->i_height;
845 error = build_height(&ip->i_inode, h); 809 while(size > arr[height])
846 up_write(&ip->i_rw_mutex); 810 height++;
847 if (error) 811 error = build_height(&ip->i_inode, height);
848 goto out_end_trans;
849 } 812 }
813 up_write(&ip->i_rw_mutex);
814 if (error)
815 goto out_end_trans;
850 } 816 }
851 817
852 ip->i_di.di_size = size; 818 ip->i_di.di_size = size;
@@ -989,7 +955,7 @@ out:
989 955
990static int trunc_dealloc(struct gfs2_inode *ip, u64 size) 956static int trunc_dealloc(struct gfs2_inode *ip, u64 size)
991{ 957{
992 unsigned int height = ip->i_di.di_height; 958 unsigned int height = ip->i_height;
993 u64 lblock; 959 u64 lblock;
994 struct metapath mp; 960 struct metapath mp;
995 int error; 961 int error;
@@ -1040,7 +1006,7 @@ static int trunc_end(struct gfs2_inode *ip)
1040 goto out; 1006 goto out;
1041 1007
1042 if (!ip->i_di.di_size) { 1008 if (!ip->i_di.di_size) {
1043 ip->i_di.di_height = 0; 1009 ip->i_height = 0;
1044 ip->i_di.di_goal_meta = 1010 ip->i_di.di_goal_meta =
1045 ip->i_di.di_goal_data = 1011 ip->i_di.di_goal_data =
1046 ip->i_no_addr; 1012 ip->i_no_addr;