aboutsummaryrefslogtreecommitdiffstats
path: root/fs/gfs2
diff options
context:
space:
mode:
Diffstat (limited to 'fs/gfs2')
-rw-r--r--fs/gfs2/bmap.c131
-rw-r--r--fs/gfs2/bmap.h2
-rw-r--r--fs/gfs2/log.c14
-rw-r--r--fs/gfs2/ops_address.c68
-rw-r--r--fs/gfs2/quota.c8
-rw-r--r--fs/gfs2/recovery.c10
6 files changed, 92 insertions, 141 deletions
diff --git a/fs/gfs2/bmap.c b/fs/gfs2/bmap.c
index 57caad7bc0d5..cc91e482eda0 100644
--- a/fs/gfs2/bmap.c
+++ b/fs/gfs2/bmap.c
@@ -423,8 +423,7 @@ static int lookup_block(struct gfs2_inode *ip, struct buffer_head *bh,
423 * gfs2_block_pointers - Map a block from an inode to a disk block 423 * gfs2_block_pointers - Map a block from an inode to a disk block
424 * @inode: The inode 424 * @inode: The inode
425 * @lblock: The logical block number 425 * @lblock: The logical block number
426 * @new: Value/Result argument (1 = may create/did create new blocks) 426 * @map_bh: The bh to be mapped
427 * @boundary: gets set if we've hit a block boundary
428 * @mp: metapath to use 427 * @mp: metapath to use
429 * 428 *
430 * Find the block number on the current device which corresponds to an 429 * Find the block number on the current device which corresponds to an
@@ -433,37 +432,35 @@ static int lookup_block(struct gfs2_inode *ip, struct buffer_head *bh,
433 * Returns: errno 432 * Returns: errno
434 */ 433 */
435 434
436static struct buffer_head *gfs2_block_pointers(struct inode *inode, u64 lblock, 435static int gfs2_block_pointers(struct inode *inode, u64 lblock, int create,
437 int *new, u64 *dblock, 436 struct buffer_head *bh_map, struct metapath *mp,
438 int *boundary, 437 unsigned int maxlen)
439 struct metapath *mp)
440{ 438{
441 struct gfs2_inode *ip = GFS2_I(inode); 439 struct gfs2_inode *ip = GFS2_I(inode);
442 struct gfs2_sbd *sdp = GFS2_SB(inode); 440 struct gfs2_sbd *sdp = GFS2_SB(inode);
443 struct buffer_head *bh; 441 struct buffer_head *bh;
444 int create = *new;
445 unsigned int bsize; 442 unsigned int bsize;
446 unsigned int height; 443 unsigned int height;
447 unsigned int end_of_metadata; 444 unsigned int end_of_metadata;
448 unsigned int x; 445 unsigned int x;
449 int error = 0; 446 int error = 0;
450 447 int new = 0;
451 *new = 0; 448 u64 dblock = 0;
452 *dblock = 0; 449 int boundary;
453 450
454 if (gfs2_assert_warn(sdp, !gfs2_is_stuffed(ip))) 451 if (gfs2_assert_warn(sdp, !gfs2_is_stuffed(ip)))
455 goto out; 452 return 0;
456 453
457 bsize = gfs2_is_dir(ip) ? sdp->sd_jbsize : sdp->sd_sb.sb_bsize; 454 bsize = gfs2_is_dir(ip) ? sdp->sd_jbsize : sdp->sd_sb.sb_bsize;
458 455
459 height = calc_tree_height(ip, (lblock + 1) * bsize); 456 height = calc_tree_height(ip, (lblock + 1) * bsize);
460 if (ip->i_di.di_height < height) { 457 if (ip->i_di.di_height < height) {
461 if (!create) 458 if (!create)
462 goto out; 459 return 0;
463 460
464 error = build_height(inode, height); 461 error = build_height(inode, height);
465 if (error) 462 if (error)
466 goto out; 463 return error;
467 } 464 }
468 465
469 find_metapath(ip, lblock, mp); 466 find_metapath(ip, lblock, mp);
@@ -471,32 +468,54 @@ static struct buffer_head *gfs2_block_pointers(struct inode *inode, u64 lblock,
471 468
472 error = gfs2_meta_inode_buffer(ip, &bh); 469 error = gfs2_meta_inode_buffer(ip, &bh);
473 if (error) 470 if (error)
474 goto out; 471 return error;
475 472
476 for (x = 0; x < end_of_metadata; x++) { 473 for (x = 0; x < end_of_metadata; x++) {
477 lookup_block(ip, bh, x, mp, create, new, dblock); 474 lookup_block(ip, bh, x, mp, create, &new, &dblock);
478 brelse(bh); 475 brelse(bh);
479 if (!*dblock) 476 if (!dblock)
480 goto out; 477 return 0;
481 478
482 error = gfs2_meta_indirect_buffer(ip, x+1, *dblock, *new, &bh); 479 error = gfs2_meta_indirect_buffer(ip, x+1, dblock, new, &bh);
483 if (error) 480 if (error)
484 goto out; 481 return error;
485 } 482 }
486 483
487 *boundary = lookup_block(ip, bh, end_of_metadata, mp, create, new, dblock); 484 boundary = lookup_block(ip, bh, end_of_metadata, mp, create, &new, &dblock);
488 if (*new) { 485 clear_buffer_mapped(bh_map);
489 struct buffer_head *dibh; 486 clear_buffer_new(bh_map);
490 error = gfs2_meta_inode_buffer(ip, &dibh); 487 clear_buffer_boundary(bh_map);
491 if (!error) { 488
492 gfs2_trans_add_bh(ip->i_gl, dibh, 1); 489 if (dblock) {
493 gfs2_dinode_out(&ip->i_di, dibh->b_data); 490 map_bh(bh_map, inode->i_sb, dblock);
494 brelse(dibh); 491 if (boundary)
492 set_buffer_boundary(bh);
493 if (new) {
494 struct buffer_head *dibh;
495 error = gfs2_meta_inode_buffer(ip, &dibh);
496 if (!error) {
497 gfs2_trans_add_bh(ip->i_gl, dibh, 1);
498 gfs2_dinode_out(&ip->i_di, dibh->b_data);
499 brelse(dibh);
500 }
501 set_buffer_new(bh_map);
502 goto out_brelse;
503 }
504 while(--maxlen && !buffer_boundary(bh_map)) {
505 u64 eblock;
506
507 mp->mp_list[end_of_metadata]++;
508 boundary = lookup_block(ip, bh, end_of_metadata, mp, 0, &new, &eblock);
509 if (eblock != ++dblock)
510 break;
511 bh_map->b_size += inode->i_blksize;
512 if (boundary)
513 set_buffer_boundary(bh_map);
495 } 514 }
496 } 515 }
497 return bh; 516out_brelse:
498out: 517 brelse(bh);
499 return ERR_PTR(error); 518 return 0;
500} 519}
501 520
502 521
@@ -518,30 +537,23 @@ static inline void bmap_unlock(struct inode *inode, int create)
518 up_read(&ip->i_rw_mutex); 537 up_read(&ip->i_rw_mutex);
519} 538}
520 539
521int gfs2_block_map(struct inode *inode, u64 lblock, int *new, u64 *dblock, int *boundary) 540int gfs2_block_map(struct inode *inode, u64 lblock, int create,
541 struct buffer_head *bh, unsigned int maxlen)
522{ 542{
523 struct metapath mp; 543 struct metapath mp;
524 struct buffer_head *bh; 544 int ret;
525 int create = *new;
526 545
527 bmap_lock(inode, create); 546 bmap_lock(inode, create);
528 bh = gfs2_block_pointers(inode, lblock, new, dblock, boundary, &mp); 547 ret = gfs2_block_pointers(inode, lblock, create, bh, &mp, maxlen);
529 bmap_unlock(inode, create); 548 bmap_unlock(inode, create);
530 if (!bh) 549 return ret;
531 return 0;
532 if (IS_ERR(bh))
533 return PTR_ERR(bh);
534 brelse(bh);
535 return 0;
536} 550}
537 551
538int gfs2_extent_map(struct inode *inode, u64 lblock, int *new, u64 *dblock, unsigned *extlen) 552int gfs2_extent_map(struct inode *inode, u64 lblock, int *new, u64 *dblock, unsigned *extlen)
539{ 553{
540 struct gfs2_inode *ip = GFS2_I(inode);
541 struct gfs2_sbd *sdp = GFS2_SB(inode);
542 struct metapath mp; 554 struct metapath mp;
543 struct buffer_head *bh; 555 struct buffer_head bh = { .b_state = 0, .b_blocknr = 0, .b_size = 0 };
544 int boundary; 556 int ret;
545 int create = *new; 557 int create = *new;
546 558
547 BUG_ON(!extlen); 559 BUG_ON(!extlen);
@@ -549,30 +561,15 @@ int gfs2_extent_map(struct inode *inode, u64 lblock, int *new, u64 *dblock, unsi
549 BUG_ON(!new); 561 BUG_ON(!new);
550 562
551 bmap_lock(inode, create); 563 bmap_lock(inode, create);
552 bh = gfs2_block_pointers(inode, lblock, new, dblock, &boundary, &mp); 564 ret = gfs2_block_pointers(inode, lblock, create, &bh, &mp, *extlen);
553 *extlen = 1;
554
555 if (bh != NULL && !IS_ERR(bh) && *dblock != 0 && *new == 0) {
556 u64 tmp_dblock;
557 int tmp_new;
558 unsigned int nptrs;
559 unsigned end_of_metadata = ip->i_di.di_height - 1;
560
561 nptrs = (end_of_metadata) ? sdp->sd_inptrs : sdp->sd_diptrs;
562 while (++mp.mp_list[end_of_metadata] < nptrs) {
563 lookup_block(ip, bh, end_of_metadata, &mp, 0, &tmp_new, &tmp_dblock);
564 if (*dblock + *extlen != tmp_dblock)
565 break;
566 ++*extlen;
567 }
568 }
569 bmap_unlock(inode, create); 565 bmap_unlock(inode, create);
570 if (!bh) 566 *extlen = bh.b_size >> inode->i_blkbits;
571 return 0; 567 *dblock = bh.b_blocknr;
572 if (IS_ERR(bh)) 568 if (buffer_new(&bh))
573 return PTR_ERR(bh); 569 *new = 1;
574 brelse(bh); 570 else
575 return 0; 571 *new = 0;
572 return ret;
576} 573}
577 574
578/** 575/**
diff --git a/fs/gfs2/bmap.h b/fs/gfs2/bmap.h
index 503f1cdda290..0fd379b4cd9e 100644
--- a/fs/gfs2/bmap.h
+++ b/fs/gfs2/bmap.h
@@ -15,7 +15,7 @@ struct gfs2_inode;
15struct page; 15struct page;
16 16
17int gfs2_unstuff_dinode(struct gfs2_inode *ip, struct page *page); 17int gfs2_unstuff_dinode(struct gfs2_inode *ip, struct page *page);
18int gfs2_block_map(struct inode *inode, u64 lblock, int *new, u64 *dblock, int *boundary); 18int gfs2_block_map(struct inode *inode, u64 lblock, int create, struct buffer_head *bh, unsigned int maxlen);
19int gfs2_extent_map(struct inode *inode, u64 lblock, int *new, u64 *dblock, unsigned *extlen); 19int gfs2_extent_map(struct inode *inode, u64 lblock, int *new, u64 *dblock, unsigned *extlen);
20 20
21int gfs2_truncatei(struct gfs2_inode *ip, u64 size); 21int gfs2_truncatei(struct gfs2_inode *ip, u64 size);
diff --git a/fs/gfs2/log.c b/fs/gfs2/log.c
index 50f88059c3d5..ab341cd0a76a 100644
--- a/fs/gfs2/log.c
+++ b/fs/gfs2/log.c
@@ -204,17 +204,15 @@ void gfs2_log_release(struct gfs2_sbd *sdp, unsigned int blks)
204 204
205static u64 log_bmap(struct gfs2_sbd *sdp, unsigned int lbn) 205static u64 log_bmap(struct gfs2_sbd *sdp, unsigned int lbn)
206{ 206{
207 int new = 0;
208 u64 dbn;
209 int error; 207 int error;
210 int bdy; 208 struct buffer_head bh_map;
211 209
212 error = gfs2_block_map(sdp->sd_jdesc->jd_inode, lbn, &new, &dbn, &bdy); 210 error = gfs2_block_map(sdp->sd_jdesc->jd_inode, lbn, 0, &bh_map, 1);
213 if (error || !dbn) 211 if (error || !bh_map.b_blocknr)
214 printk(KERN_INFO "error=%d, dbn=%llu lbn=%u", error, (unsigned long long)dbn, lbn); 212 printk(KERN_INFO "error=%d, dbn=%llu lbn=%u", error, bh_map.b_blocknr, lbn);
215 gfs2_assert_withdraw(sdp, !error && dbn); 213 gfs2_assert_withdraw(sdp, !error && bh_map.b_blocknr);
216 214
217 return dbn; 215 return bh_map.b_blocknr;
218} 216}
219 217
220/** 218/**
diff --git a/fs/gfs2/ops_address.c b/fs/gfs2/ops_address.c
index d44d42fb4163..6f9ac5e6e3f6 100644
--- a/fs/gfs2/ops_address.c
+++ b/fs/gfs2/ops_address.c
@@ -65,29 +65,11 @@ static void gfs2_page_add_databufs(struct gfs2_inode *ip, struct page *page,
65int gfs2_get_block(struct inode *inode, sector_t lblock, 65int gfs2_get_block(struct inode *inode, sector_t lblock,
66 struct buffer_head *bh_result, int create) 66 struct buffer_head *bh_result, int create)
67{ 67{
68 int new = create; 68 return gfs2_block_map(inode, lblock, create, bh_result, 32);
69 u64 dblock;
70 int error;
71 int boundary;
72
73 error = gfs2_block_map(inode, lblock, &new, &dblock, &boundary);
74 if (error)
75 return error;
76
77 if (!dblock)
78 return 0;
79
80 map_bh(bh_result, inode->i_sb, dblock);
81 if (new)
82 set_buffer_new(bh_result);
83 if (boundary)
84 set_buffer_boundary(bh_result);
85
86 return 0;
87} 69}
88 70
89/** 71/**
90 * get_block_noalloc - Fills in a buffer head with details about a block 72 * gfs2_get_block_noalloc - Fills in a buffer head with details about a block
91 * @inode: The inode 73 * @inode: The inode
92 * @lblock: The block number to look up 74 * @lblock: The block number to look up
93 * @bh_result: The buffer head to return the result in 75 * @bh_result: The buffer head to return the result in
@@ -96,47 +78,25 @@ int gfs2_get_block(struct inode *inode, sector_t lblock,
96 * Returns: errno 78 * Returns: errno
97 */ 79 */
98 80
99static int get_block_noalloc(struct inode *inode, sector_t lblock, 81static int gfs2_get_block_noalloc(struct inode *inode, sector_t lblock,
100 struct buffer_head *bh_result, int create) 82 struct buffer_head *bh_result, int create)
101{ 83{
102 int new = 0;
103 u64 dblock;
104 int error; 84 int error;
105 int boundary;
106 85
107 error = gfs2_block_map(inode, lblock, &new, &dblock, &boundary); 86 error = gfs2_block_map(inode, lblock, 0, bh_result, 1);
108 if (error) 87 if (error)
109 return error; 88 return error;
110 89 if (bh_result->b_blocknr == 0)
111 if (dblock) 90 return -EIO;
112 map_bh(bh_result, inode->i_sb, dblock); 91 return 0;
113 else if (gfs2_assert_withdraw(GFS2_SB(inode), !create))
114 error = -EIO;
115 if (boundary)
116 set_buffer_boundary(bh_result);
117
118 return error;
119} 92}
120 93
121static int get_block_direct(struct inode *inode, sector_t lblock, 94static int gfs2_get_block_direct(struct inode *inode, sector_t lblock,
122 struct buffer_head *bh_result, int create) 95 struct buffer_head *bh_result, int create)
123{ 96{
124 int new = 0; 97 return gfs2_block_map(inode, lblock, 0, bh_result, 512);
125 u64 dblock;
126 int error, boundary;
127
128 error = gfs2_block_map(inode, lblock, &new, &dblock, &boundary);
129 if (error)
130 return error;
131
132 if (dblock) {
133 map_bh(bh_result, inode->i_sb, dblock);
134 if (boundary)
135 set_buffer_boundary(bh_result);
136 }
137
138 return 0;
139} 98}
99
140/** 100/**
141 * gfs2_writepage - Write complete page 101 * gfs2_writepage - Write complete page
142 * @page: Page to write 102 * @page: Page to write
@@ -184,7 +144,7 @@ static int gfs2_writepage(struct page *page, struct writeback_control *wbc)
184 gfs2_page_add_databufs(ip, page, 0, sdp->sd_vfs->s_blocksize-1); 144 gfs2_page_add_databufs(ip, page, 0, sdp->sd_vfs->s_blocksize-1);
185 done_trans = 1; 145 done_trans = 1;
186 } 146 }
187 error = block_write_full_page(page, get_block_noalloc, wbc); 147 error = block_write_full_page(page, gfs2_get_block_noalloc, wbc);
188 if (done_trans) 148 if (done_trans)
189 gfs2_trans_end(sdp); 149 gfs2_trans_end(sdp);
190 gfs2_meta_cache_flush(ip); 150 gfs2_meta_cache_flush(ip);
@@ -680,7 +640,7 @@ static ssize_t gfs2_direct_IO(int rw, struct kiocb *iocb,
680 rv = blockdev_direct_IO_own_locking(rw, iocb, inode, 640 rv = blockdev_direct_IO_own_locking(rw, iocb, inode,
681 inode->i_sb->s_bdev, 641 inode->i_sb->s_bdev,
682 iov, offset, nr_segs, 642 iov, offset, nr_segs,
683 get_block_direct, NULL); 643 gfs2_get_block_direct, NULL);
684out: 644out:
685 gfs2_glock_dq_m(1, &gh); 645 gfs2_glock_dq_m(1, &gh);
686 gfs2_holder_uninit(&gh); 646 gfs2_holder_uninit(&gh);
diff --git a/fs/gfs2/quota.c b/fs/gfs2/quota.c
index fe1828ffebfa..bc9ad058d20e 100644
--- a/fs/gfs2/quota.c
+++ b/fs/gfs2/quota.c
@@ -248,11 +248,9 @@ static int bh_get(struct gfs2_quota_data *qd)
248 struct gfs2_sbd *sdp = qd->qd_gl->gl_sbd; 248 struct gfs2_sbd *sdp = qd->qd_gl->gl_sbd;
249 struct gfs2_inode *ip = GFS2_I(sdp->sd_qc_inode); 249 struct gfs2_inode *ip = GFS2_I(sdp->sd_qc_inode);
250 unsigned int block, offset; 250 unsigned int block, offset;
251 u64 dblock;
252 int new = 0;
253 struct buffer_head *bh; 251 struct buffer_head *bh;
254 int error; 252 int error;
255 int boundary; 253 struct buffer_head bh_map;
256 254
257 mutex_lock(&sdp->sd_quota_mutex); 255 mutex_lock(&sdp->sd_quota_mutex);
258 256
@@ -264,10 +262,10 @@ static int bh_get(struct gfs2_quota_data *qd)
264 block = qd->qd_slot / sdp->sd_qc_per_block; 262 block = qd->qd_slot / sdp->sd_qc_per_block;
265 offset = qd->qd_slot % sdp->sd_qc_per_block;; 263 offset = qd->qd_slot % sdp->sd_qc_per_block;;
266 264
267 error = gfs2_block_map(&ip->i_inode, block, &new, &dblock, &boundary); 265 error = gfs2_block_map(&ip->i_inode, block, 0, &bh_map, 1);
268 if (error) 266 if (error)
269 goto fail; 267 goto fail;
270 error = gfs2_meta_read(ip->i_gl, dblock, DIO_START | DIO_WAIT, &bh); 268 error = gfs2_meta_read(ip->i_gl, bh_map.b_blocknr, DIO_START | DIO_WAIT, &bh);
271 if (error) 269 if (error)
272 goto fail; 270 goto fail;
273 error = -EIO; 271 error = -EIO;
diff --git a/fs/gfs2/recovery.c b/fs/gfs2/recovery.c
index a27569c5d85e..130e9fbf9692 100644
--- a/fs/gfs2/recovery.c
+++ b/fs/gfs2/recovery.c
@@ -369,25 +369,23 @@ static int clean_journal(struct gfs2_jdesc *jd, struct gfs2_log_header *head)
369 struct gfs2_inode *ip = GFS2_I(jd->jd_inode); 369 struct gfs2_inode *ip = GFS2_I(jd->jd_inode);
370 struct gfs2_sbd *sdp = GFS2_SB(jd->jd_inode); 370 struct gfs2_sbd *sdp = GFS2_SB(jd->jd_inode);
371 unsigned int lblock; 371 unsigned int lblock;
372 int new = 0;
373 u64 dblock;
374 struct gfs2_log_header *lh; 372 struct gfs2_log_header *lh;
375 u32 hash; 373 u32 hash;
376 struct buffer_head *bh; 374 struct buffer_head *bh;
377 int error; 375 int error;
378 int boundary; 376 struct buffer_head bh_map;
379 377
380 lblock = head->lh_blkno; 378 lblock = head->lh_blkno;
381 gfs2_replay_incr_blk(sdp, &lblock); 379 gfs2_replay_incr_blk(sdp, &lblock);
382 error = gfs2_block_map(&ip->i_inode, lblock, &new, &dblock, &boundary); 380 error = gfs2_block_map(&ip->i_inode, lblock, 0, &bh_map, 1);
383 if (error) 381 if (error)
384 return error; 382 return error;
385 if (!dblock) { 383 if (!bh_map.b_blocknr) {
386 gfs2_consist_inode(ip); 384 gfs2_consist_inode(ip);
387 return -EIO; 385 return -EIO;
388 } 386 }
389 387
390 bh = sb_getblk(sdp->sd_vfs, dblock); 388 bh = sb_getblk(sdp->sd_vfs, bh_map.b_blocknr);
391 lock_buffer(bh); 389 lock_buffer(bh);
392 memset(bh->b_data, 0, bh->b_size); 390 memset(bh->b_data, 0, bh->b_size);
393 set_buffer_uptodate(bh); 391 set_buffer_uptodate(bh);