aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--fs/gfs2/bmap.c108
-rw-r--r--fs/gfs2/incore.h6
-rw-r--r--fs/gfs2/inode.c20
-rw-r--r--fs/gfs2/inode.h2
-rw-r--r--fs/gfs2/super.c2
5 files changed, 55 insertions, 83 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;
diff --git a/fs/gfs2/incore.h b/fs/gfs2/incore.h
index 525dcae352d6..43472baa92e7 100644
--- a/fs/gfs2/incore.h
+++ b/fs/gfs2/incore.h
@@ -246,7 +246,6 @@ struct gfs2_dinode_host {
246 u64 di_goal_data; /* data block goal */ 246 u64 di_goal_data; /* data block goal */
247 u64 di_generation; /* generation number for NFS */ 247 u64 di_generation; /* generation number for NFS */
248 u32 di_flags; /* GFS2_DIF_... */ 248 u32 di_flags; /* GFS2_DIF_... */
249 u16 di_height; /* height of metadata */
250 /* These only apply to directories */ 249 /* These only apply to directories */
251 u16 di_depth; /* Number of bits in the table */ 250 u16 di_depth; /* Number of bits in the table */
252 u32 di_entries; /* The number of entries in the directory */ 251 u32 di_entries; /* The number of entries in the directory */
@@ -268,6 +267,7 @@ struct gfs2_inode {
268 u64 i_last_rg_alloc; 267 u64 i_last_rg_alloc;
269 268
270 struct rw_semaphore i_rw_mutex; 269 struct rw_semaphore i_rw_mutex;
270 u8 i_height;
271}; 271};
272 272
273/* 273/*
@@ -490,9 +490,9 @@ struct gfs2_sbd {
490 u32 sd_qc_per_block; 490 u32 sd_qc_per_block;
491 u32 sd_max_dirres; /* Max blocks needed to add a directory entry */ 491 u32 sd_max_dirres; /* Max blocks needed to add a directory entry */
492 u32 sd_max_height; /* Max height of a file's metadata tree */ 492 u32 sd_max_height; /* Max height of a file's metadata tree */
493 u64 sd_heightsize[GFS2_MAX_META_HEIGHT]; 493 u64 sd_heightsize[GFS2_MAX_META_HEIGHT + 1];
494 u32 sd_max_jheight; /* Max height of journaled file's meta tree */ 494 u32 sd_max_jheight; /* Max height of journaled file's meta tree */
495 u64 sd_jheightsize[GFS2_MAX_META_HEIGHT]; 495 u64 sd_jheightsize[GFS2_MAX_META_HEIGHT + 1];
496 496
497 struct gfs2_args sd_args; /* Mount arguments */ 497 struct gfs2_args sd_args; /* Mount arguments */
498 struct gfs2_tune sd_tune; /* Filesystem tuning structure */ 498 struct gfs2_tune sd_tune; /* Filesystem tuning structure */
diff --git a/fs/gfs2/inode.c b/fs/gfs2/inode.c
index 37725ade3c51..ff66ab7a17c8 100644
--- a/fs/gfs2/inode.c
+++ b/fs/gfs2/inode.c
@@ -248,12 +248,10 @@ static int gfs2_dinode_in(struct gfs2_inode *ip, const void *buf)
248{ 248{
249 struct gfs2_dinode_host *di = &ip->i_di; 249 struct gfs2_dinode_host *di = &ip->i_di;
250 const struct gfs2_dinode *str = buf; 250 const struct gfs2_dinode *str = buf;
251 u16 height;
251 252
252 if (ip->i_no_addr != be64_to_cpu(str->di_num.no_addr)) { 253 if (unlikely(ip->i_no_addr != be64_to_cpu(str->di_num.no_addr)))
253 if (gfs2_consist_inode(ip)) 254 goto corrupt;
254 gfs2_dinode_print(ip);
255 return -EIO;
256 }
257 ip->i_no_formal_ino = be64_to_cpu(str->di_num.no_formal_ino); 255 ip->i_no_formal_ino = be64_to_cpu(str->di_num.no_formal_ino);
258 ip->i_inode.i_mode = be32_to_cpu(str->di_mode); 256 ip->i_inode.i_mode = be32_to_cpu(str->di_mode);
259 ip->i_inode.i_rdev = 0; 257 ip->i_inode.i_rdev = 0;
@@ -290,7 +288,10 @@ static int gfs2_dinode_in(struct gfs2_inode *ip, const void *buf)
290 288
291 di->di_flags = be32_to_cpu(str->di_flags); 289 di->di_flags = be32_to_cpu(str->di_flags);
292 gfs2_set_inode_flags(&ip->i_inode); 290 gfs2_set_inode_flags(&ip->i_inode);
293 di->di_height = be16_to_cpu(str->di_height); 291 height = be16_to_cpu(str->di_height);
292 if (unlikely(height > GFS2_MAX_META_HEIGHT))
293 goto corrupt;
294 ip->i_height = (u8)height;
294 295
295 di->di_depth = be16_to_cpu(str->di_depth); 296 di->di_depth = be16_to_cpu(str->di_depth);
296 di->di_entries = be32_to_cpu(str->di_entries); 297 di->di_entries = be32_to_cpu(str->di_entries);
@@ -300,6 +301,10 @@ static int gfs2_dinode_in(struct gfs2_inode *ip, const void *buf)
300 gfs2_set_aops(&ip->i_inode); 301 gfs2_set_aops(&ip->i_inode);
301 302
302 return 0; 303 return 0;
304corrupt:
305 if (gfs2_consist_inode(ip))
306 gfs2_dinode_print(ip);
307 return -EIO;
303} 308}
304 309
305/** 310/**
@@ -1401,7 +1406,7 @@ void gfs2_dinode_out(const struct gfs2_inode *ip, void *buf)
1401 str->di_generation = cpu_to_be64(di->di_generation); 1406 str->di_generation = cpu_to_be64(di->di_generation);
1402 1407
1403 str->di_flags = cpu_to_be32(di->di_flags); 1408 str->di_flags = cpu_to_be32(di->di_flags);
1404 str->di_height = cpu_to_be16(di->di_height); 1409 str->di_height = cpu_to_be16(ip->i_height);
1405 str->di_payload_format = cpu_to_be32(S_ISDIR(ip->i_inode.i_mode) && 1410 str->di_payload_format = cpu_to_be32(S_ISDIR(ip->i_inode.i_mode) &&
1406 !(ip->i_di.di_flags & GFS2_DIF_EXHASH) ? 1411 !(ip->i_di.di_flags & GFS2_DIF_EXHASH) ?
1407 GFS2_FORMAT_DE : 0); 1412 GFS2_FORMAT_DE : 0);
@@ -1430,7 +1435,6 @@ void gfs2_dinode_print(const struct gfs2_inode *ip)
1430 printk(KERN_INFO " di_goal_data = %llu\n", 1435 printk(KERN_INFO " di_goal_data = %llu\n",
1431 (unsigned long long)di->di_goal_data); 1436 (unsigned long long)di->di_goal_data);
1432 printk(KERN_INFO " di_flags = 0x%.8X\n", di->di_flags); 1437 printk(KERN_INFO " di_flags = 0x%.8X\n", di->di_flags);
1433 printk(KERN_INFO " di_height = %u\n", di->di_height);
1434 printk(KERN_INFO " di_depth = %u\n", di->di_depth); 1438 printk(KERN_INFO " di_depth = %u\n", di->di_depth);
1435 printk(KERN_INFO " di_entries = %u\n", di->di_entries); 1439 printk(KERN_INFO " di_entries = %u\n", di->di_entries);
1436 printk(KERN_INFO " di_eattr = %llu\n", 1440 printk(KERN_INFO " di_eattr = %llu\n",
diff --git a/fs/gfs2/inode.h b/fs/gfs2/inode.h
index d44650662615..db738686ca1d 100644
--- a/fs/gfs2/inode.h
+++ b/fs/gfs2/inode.h
@@ -12,7 +12,7 @@
12 12
13static inline int gfs2_is_stuffed(const struct gfs2_inode *ip) 13static inline int gfs2_is_stuffed(const struct gfs2_inode *ip)
14{ 14{
15 return !ip->i_di.di_height; 15 return !ip->i_height;
16} 16}
17 17
18static inline int gfs2_is_jdata(const struct gfs2_inode *ip) 18static inline int gfs2_is_jdata(const struct gfs2_inode *ip)
diff --git a/fs/gfs2/super.c b/fs/gfs2/super.c
index ef0562c3bc71..88497b0b7339 100644
--- a/fs/gfs2/super.c
+++ b/fs/gfs2/super.c
@@ -316,6 +316,7 @@ int gfs2_read_sb(struct gfs2_sbd *sdp, struct gfs2_glock *gl, int silent)
316 sdp->sd_heightsize[x] = space; 316 sdp->sd_heightsize[x] = space;
317 } 317 }
318 sdp->sd_max_height = x; 318 sdp->sd_max_height = x;
319 sdp->sd_heightsize[x] = ~0;
319 gfs2_assert(sdp, sdp->sd_max_height <= GFS2_MAX_META_HEIGHT); 320 gfs2_assert(sdp, sdp->sd_max_height <= GFS2_MAX_META_HEIGHT);
320 321
321 sdp->sd_jheightsize[0] = sdp->sd_sb.sb_bsize - 322 sdp->sd_jheightsize[0] = sdp->sd_sb.sb_bsize -
@@ -334,6 +335,7 @@ int gfs2_read_sb(struct gfs2_sbd *sdp, struct gfs2_glock *gl, int silent)
334 sdp->sd_jheightsize[x] = space; 335 sdp->sd_jheightsize[x] = space;
335 } 336 }
336 sdp->sd_max_jheight = x; 337 sdp->sd_max_jheight = x;
338 sdp->sd_jheightsize[x] = ~0;
337 gfs2_assert(sdp, sdp->sd_max_jheight <= GFS2_MAX_META_HEIGHT); 339 gfs2_assert(sdp, sdp->sd_max_jheight <= GFS2_MAX_META_HEIGHT);
338 340
339 return 0; 341 return 0;