aboutsummaryrefslogtreecommitdiffstats
path: root/fs/gfs2/rgrp.c
diff options
context:
space:
mode:
authorSteven Whitehouse <swhiteho@redhat.com>2011-08-31 11:38:29 -0400
committerSteven Whitehouse <swhiteho@redhat.com>2011-10-21 07:39:33 -0400
commit8339ee543ece6e2dcc1bbd97d5350163c198cf00 (patch)
tree80b3d4b990a8ab5f8b7c28945f694b01301c05c6 /fs/gfs2/rgrp.c
parent7c9ca621137cde26be05448133fc1a554345f4f8 (diff)
GFS2: Make resource groups "append only" during life of fs
Since we have ruled out supporting online filesystem shrink, it is possible to make the resource group list append only during the life of a super block. This gives several benefits: Firstly, we only need to read new rindex elements as they are added rather than needing to reread the whole rindex file each time one element is added. Secondly, the rindex glock can be held for much shorter periods of time, and is completely removed from the fast path for allocations. The lock is taken in shared mode only when updating the resource groups when the first allocation occurs, and after a grow has taken place. Thirdly, this results in a reduction in code size, and everything gets a lot simpler to understand in this area. Signed-off-by: Steven Whitehouse <swhiteho@redhat.com>
Diffstat (limited to 'fs/gfs2/rgrp.c')
-rw-r--r--fs/gfs2/rgrp.c168
1 files changed, 72 insertions, 96 deletions
diff --git a/fs/gfs2/rgrp.c b/fs/gfs2/rgrp.c
index 00f6e3d62c22..88d5b75067a8 100644
--- a/fs/gfs2/rgrp.c
+++ b/fs/gfs2/rgrp.c
@@ -332,14 +332,10 @@ struct gfs2_rgrpd *gfs2_blk2rgrpd(struct gfs2_sbd *sdp, u64 blk)
332 struct rb_node **newn, *parent = NULL; 332 struct rb_node **newn, *parent = NULL;
333 333
334 spin_lock(&sdp->sd_rindex_spin); 334 spin_lock(&sdp->sd_rindex_spin);
335
336 newn = &sdp->sd_rindex_tree.rb_node; 335 newn = &sdp->sd_rindex_tree.rb_node;
337
338 /* Figure out where to put new node */
339 while (*newn) { 336 while (*newn) {
340 struct gfs2_rgrpd *cur = rb_entry(*newn, struct gfs2_rgrpd, 337 struct gfs2_rgrpd *cur = rb_entry(*newn, struct gfs2_rgrpd,
341 rd_node); 338 rd_node);
342
343 parent = *newn; 339 parent = *newn;
344 if (blk < cur->rd_addr) 340 if (blk < cur->rd_addr)
345 newn = &((*newn)->rb_left); 341 newn = &((*newn)->rb_left);
@@ -350,7 +346,6 @@ struct gfs2_rgrpd *gfs2_blk2rgrpd(struct gfs2_sbd *sdp, u64 blk)
350 return cur; 346 return cur;
351 } 347 }
352 } 348 }
353
354 spin_unlock(&sdp->sd_rindex_spin); 349 spin_unlock(&sdp->sd_rindex_spin);
355 350
356 return NULL; 351 return NULL;
@@ -368,8 +363,10 @@ struct gfs2_rgrpd *gfs2_rgrpd_get_first(struct gfs2_sbd *sdp)
368 const struct rb_node *n; 363 const struct rb_node *n;
369 struct gfs2_rgrpd *rgd; 364 struct gfs2_rgrpd *rgd;
370 365
366 spin_lock(&sdp->sd_rindex_spin);
371 n = rb_first(&sdp->sd_rindex_tree); 367 n = rb_first(&sdp->sd_rindex_tree);
372 rgd = rb_entry(n, struct gfs2_rgrpd, rd_node); 368 rgd = rb_entry(n, struct gfs2_rgrpd, rd_node);
369 spin_unlock(&sdp->sd_rindex_spin);
373 370
374 return rgd; 371 return rgd;
375} 372}
@@ -400,7 +397,18 @@ struct gfs2_rgrpd *gfs2_rgrpd_get_next(struct gfs2_rgrpd *rgd)
400 return rgd; 397 return rgd;
401} 398}
402 399
403static void clear_rgrpdi(struct gfs2_sbd *sdp) 400void gfs2_free_clones(struct gfs2_rgrpd *rgd)
401{
402 int x;
403
404 for (x = 0; x < rgd->rd_length; x++) {
405 struct gfs2_bitmap *bi = rgd->rd_bits + x;
406 kfree(bi->bi_clone);
407 bi->bi_clone = NULL;
408 }
409}
410
411void gfs2_clear_rgrpd(struct gfs2_sbd *sdp)
404{ 412{
405 struct rb_node *n; 413 struct rb_node *n;
406 struct gfs2_rgrpd *rgd; 414 struct gfs2_rgrpd *rgd;
@@ -413,23 +421,19 @@ static void clear_rgrpdi(struct gfs2_sbd *sdp)
413 rb_erase(n, &sdp->sd_rindex_tree); 421 rb_erase(n, &sdp->sd_rindex_tree);
414 422
415 if (gl) { 423 if (gl) {
424 spin_lock(&gl->gl_spin);
416 gl->gl_object = NULL; 425 gl->gl_object = NULL;
426 spin_unlock(&gl->gl_spin);
417 gfs2_glock_add_to_lru(gl); 427 gfs2_glock_add_to_lru(gl);
418 gfs2_glock_put(gl); 428 gfs2_glock_put(gl);
419 } 429 }
420 430
431 gfs2_free_clones(rgd);
421 kfree(rgd->rd_bits); 432 kfree(rgd->rd_bits);
422 kmem_cache_free(gfs2_rgrpd_cachep, rgd); 433 kmem_cache_free(gfs2_rgrpd_cachep, rgd);
423 } 434 }
424} 435}
425 436
426void gfs2_clear_rgrpd(struct gfs2_sbd *sdp)
427{
428 mutex_lock(&sdp->sd_rindex_mutex);
429 clear_rgrpdi(sdp);
430 mutex_unlock(&sdp->sd_rindex_mutex);
431}
432
433static void gfs2_rindex_print(const struct gfs2_rgrpd *rgd) 437static void gfs2_rindex_print(const struct gfs2_rgrpd *rgd)
434{ 438{
435 printk(KERN_INFO " ri_addr = %llu\n", (unsigned long long)rgd->rd_addr); 439 printk(KERN_INFO " ri_addr = %llu\n", (unsigned long long)rgd->rd_addr);
@@ -546,17 +550,6 @@ u64 gfs2_ri_total(struct gfs2_sbd *sdp)
546 return total_data; 550 return total_data;
547} 551}
548 552
549static void gfs2_rindex_in(struct gfs2_rgrpd *rgd, const void *buf)
550{
551 const struct gfs2_rindex *str = buf;
552
553 rgd->rd_addr = be64_to_cpu(str->ri_addr);
554 rgd->rd_length = be32_to_cpu(str->ri_length);
555 rgd->rd_data0 = be64_to_cpu(str->ri_data0);
556 rgd->rd_data = be32_to_cpu(str->ri_data);
557 rgd->rd_bitbytes = be32_to_cpu(str->ri_bitbytes);
558}
559
560static void rgd_insert(struct gfs2_rgrpd *rgd) 553static void rgd_insert(struct gfs2_rgrpd *rgd)
561{ 554{
562 struct gfs2_sbd *sdp = rgd->rd_sbd; 555 struct gfs2_sbd *sdp = rgd->rd_sbd;
@@ -584,7 +577,7 @@ static void rgd_insert(struct gfs2_rgrpd *rgd)
584 * read_rindex_entry - Pull in a new resource index entry from the disk 577 * read_rindex_entry - Pull in a new resource index entry from the disk
585 * @gl: The glock covering the rindex inode 578 * @gl: The glock covering the rindex inode
586 * 579 *
587 * Returns: 0 on success, error code otherwise 580 * Returns: 0 on success, > 0 on EOF, error code otherwise
588 */ 581 */
589 582
590static int read_rindex_entry(struct gfs2_inode *ip, 583static int read_rindex_entry(struct gfs2_inode *ip,
@@ -592,19 +585,18 @@ static int read_rindex_entry(struct gfs2_inode *ip,
592{ 585{
593 struct gfs2_sbd *sdp = GFS2_SB(&ip->i_inode); 586 struct gfs2_sbd *sdp = GFS2_SB(&ip->i_inode);
594 loff_t pos = sdp->sd_rgrps * sizeof(struct gfs2_rindex); 587 loff_t pos = sdp->sd_rgrps * sizeof(struct gfs2_rindex);
595 char buf[sizeof(struct gfs2_rindex)]; 588 struct gfs2_rindex buf;
596 int error; 589 int error;
597 struct gfs2_rgrpd *rgd; 590 struct gfs2_rgrpd *rgd;
598 591
599 error = gfs2_internal_read(ip, ra_state, buf, &pos, 592 if (pos >= i_size_read(&ip->i_inode))
593 return 1;
594
595 error = gfs2_internal_read(ip, ra_state, (char *)&buf, &pos,
600 sizeof(struct gfs2_rindex)); 596 sizeof(struct gfs2_rindex));
601 if (!error) 597
602 return 0; 598 if (error != sizeof(struct gfs2_rindex))
603 if (error != sizeof(struct gfs2_rindex)) { 599 return (error == 0) ? 1 : error;
604 if (error > 0)
605 error = -EIO;
606 return error;
607 }
608 600
609 rgd = kmem_cache_zalloc(gfs2_rgrpd_cachep, GFP_NOFS); 601 rgd = kmem_cache_zalloc(gfs2_rgrpd_cachep, GFP_NOFS);
610 error = -ENOMEM; 602 error = -ENOMEM;
@@ -612,23 +604,34 @@ static int read_rindex_entry(struct gfs2_inode *ip,
612 return error; 604 return error;
613 605
614 rgd->rd_sbd = sdp; 606 rgd->rd_sbd = sdp;
615 607 rgd->rd_addr = be64_to_cpu(buf.ri_addr);
616 gfs2_rindex_in(rgd, buf); 608 rgd->rd_length = be32_to_cpu(buf.ri_length);
617 rgd_insert(rgd); 609 rgd->rd_data0 = be64_to_cpu(buf.ri_data0);
610 rgd->rd_data = be32_to_cpu(buf.ri_data);
611 rgd->rd_bitbytes = be32_to_cpu(buf.ri_bitbytes);
618 612
619 error = compute_bitstructs(rgd); 613 error = compute_bitstructs(rgd);
620 if (error) 614 if (error)
621 return error; 615 goto fail;
622 616
623 error = gfs2_glock_get(sdp, rgd->rd_addr, 617 error = gfs2_glock_get(sdp, rgd->rd_addr,
624 &gfs2_rgrp_glops, CREATE, &rgd->rd_gl); 618 &gfs2_rgrp_glops, CREATE, &rgd->rd_gl);
625 if (error) 619 if (error)
626 return error; 620 goto fail;
627 621
628 rgd->rd_gl->gl_object = rgd; 622 rgd->rd_gl->gl_object = rgd;
629 rgd->rd_flags &= ~GFS2_RDF_UPTODATE; 623 rgd->rd_flags &= ~GFS2_RDF_UPTODATE;
630 if (rgd->rd_data > sdp->sd_max_rg_data) 624 if (rgd->rd_data > sdp->sd_max_rg_data)
631 sdp->sd_max_rg_data = rgd->rd_data; 625 sdp->sd_max_rg_data = rgd->rd_data;
626 spin_lock(&sdp->sd_rindex_spin);
627 rgd_insert(rgd);
628 sdp->sd_rgrps++;
629 spin_unlock(&sdp->sd_rindex_spin);
630 return error;
631
632fail:
633 kfree(rgd->rd_bits);
634 kmem_cache_free(gfs2_rgrpd_cachep, rgd);
632 return error; 635 return error;
633} 636}
634 637
@@ -639,34 +642,28 @@ static int read_rindex_entry(struct gfs2_inode *ip,
639 * Returns: 0 on successful update, error code otherwise 642 * Returns: 0 on successful update, error code otherwise
640 */ 643 */
641 644
642int gfs2_ri_update(struct gfs2_inode *ip) 645static int gfs2_ri_update(struct gfs2_inode *ip)
643{ 646{
644 struct gfs2_sbd *sdp = GFS2_SB(&ip->i_inode); 647 struct gfs2_sbd *sdp = GFS2_SB(&ip->i_inode);
645 struct inode *inode = &ip->i_inode; 648 struct inode *inode = &ip->i_inode;
646 struct file_ra_state ra_state; 649 struct file_ra_state ra_state;
647 u64 rgrp_count = i_size_read(inode);
648 int error; 650 int error;
649 651
650 do_div(rgrp_count, sizeof(struct gfs2_rindex));
651 clear_rgrpdi(sdp);
652
653 file_ra_state_init(&ra_state, inode->i_mapping); 652 file_ra_state_init(&ra_state, inode->i_mapping);
654 for (sdp->sd_rgrps = 0; sdp->sd_rgrps < rgrp_count; sdp->sd_rgrps++) { 653 do {
655 error = read_rindex_entry(ip, &ra_state); 654 error = read_rindex_entry(ip, &ra_state);
656 if (error) { 655 } while (error == 0);
657 clear_rgrpdi(sdp); 656
658 return error; 657 if (error < 0)
659 } 658 return error;
660 }
661 659
662 sdp->sd_rindex_uptodate = 1; 660 sdp->sd_rindex_uptodate = 1;
663 return 0; 661 return 0;
664} 662}
665 663
666/** 664/**
667 * gfs2_rindex_hold - Grab a lock on the rindex 665 * gfs2_rindex_update - Update the rindex if required
668 * @sdp: The GFS2 superblock 666 * @sdp: The GFS2 superblock
669 * @ri_gh: the glock holder
670 * 667 *
671 * We grab a lock on the rindex inode to make sure that it doesn't 668 * We grab a lock on the rindex inode to make sure that it doesn't
672 * change whilst we are performing an operation. We keep this lock 669 * change whilst we are performing an operation. We keep this lock
@@ -678,30 +675,29 @@ int gfs2_ri_update(struct gfs2_inode *ip)
678 * special file, which might have been updated if someone expanded the 675 * special file, which might have been updated if someone expanded the
679 * filesystem (via gfs2_grow utility), which adds new resource groups. 676 * filesystem (via gfs2_grow utility), which adds new resource groups.
680 * 677 *
681 * Returns: 0 on success, error code otherwise 678 * Returns: 0 on succeess, error code otherwise
682 */ 679 */
683 680
684int gfs2_rindex_hold(struct gfs2_sbd *sdp, struct gfs2_holder *ri_gh) 681int gfs2_rindex_update(struct gfs2_sbd *sdp)
685{ 682{
686 struct gfs2_inode *ip = GFS2_I(sdp->sd_rindex); 683 struct gfs2_inode *ip = GFS2_I(sdp->sd_rindex);
687 struct gfs2_glock *gl = ip->i_gl; 684 struct gfs2_glock *gl = ip->i_gl;
688 int error; 685 struct gfs2_holder ri_gh;
689 686 int error = 0;
690 error = gfs2_glock_nq_init(gl, LM_ST_SHARED, 0, ri_gh);
691 if (error)
692 return error;
693 687
694 /* Read new copy from disk if we don't have the latest */ 688 /* Read new copy from disk if we don't have the latest */
695 if (!sdp->sd_rindex_uptodate) { 689 if (!sdp->sd_rindex_uptodate) {
696 mutex_lock(&sdp->sd_rindex_mutex); 690 mutex_lock(&sdp->sd_rindex_mutex);
697 if (!sdp->sd_rindex_uptodate) { 691 error = gfs2_glock_nq_init(gl, LM_ST_SHARED, 0, &ri_gh);
692 if (error)
693 return error;
694 if (!sdp->sd_rindex_uptodate)
698 error = gfs2_ri_update(ip); 695 error = gfs2_ri_update(ip);
699 if (error) 696 gfs2_glock_dq_uninit(&ri_gh);
700 gfs2_glock_dq_uninit(ri_gh);
701 }
702 mutex_unlock(&sdp->sd_rindex_mutex); 697 mutex_unlock(&sdp->sd_rindex_mutex);
703 } 698 }
704 699
700
705 return error; 701 return error;
706} 702}
707 703
@@ -873,8 +869,13 @@ fail:
873 869
874struct gfs2_alloc *gfs2_alloc_get(struct gfs2_inode *ip) 870struct gfs2_alloc *gfs2_alloc_get(struct gfs2_inode *ip)
875{ 871{
872 struct gfs2_sbd *sdp = GFS2_SB(&ip->i_inode);
873 int error;
876 BUG_ON(ip->i_alloc != NULL); 874 BUG_ON(ip->i_alloc != NULL);
877 ip->i_alloc = kzalloc(sizeof(struct gfs2_alloc), GFP_NOFS); 875 ip->i_alloc = kzalloc(sizeof(struct gfs2_alloc), GFP_NOFS);
876 error = gfs2_rindex_update(sdp);
877 if (error)
878 fs_warn(sdp, "rindex update returns %d\n", error);
878 return ip->i_alloc; 879 return ip->i_alloc;
879} 880}
880 881
@@ -1029,7 +1030,7 @@ static int get_local_rgrp(struct gfs2_inode *ip, u64 *last_unlinked)
1029 * Returns: errno 1030 * Returns: errno
1030 */ 1031 */
1031 1032
1032int gfs2_inplace_reserve_i(struct gfs2_inode *ip, int hold_rindex, 1033int gfs2_inplace_reserve_i(struct gfs2_inode *ip,
1033 char *file, unsigned int line) 1034 char *file, unsigned int line)
1034{ 1035{
1035 struct gfs2_sbd *sdp = GFS2_SB(&ip->i_inode); 1036 struct gfs2_sbd *sdp = GFS2_SB(&ip->i_inode);
@@ -1041,18 +1042,6 @@ int gfs2_inplace_reserve_i(struct gfs2_inode *ip, int hold_rindex,
1041 if (gfs2_assert_warn(sdp, al->al_requested)) 1042 if (gfs2_assert_warn(sdp, al->al_requested))
1042 return -EINVAL; 1043 return -EINVAL;
1043 1044
1044 if (hold_rindex) {
1045 /* We need to hold the rindex unless the inode we're using is
1046 the rindex itself, in which case it's already held. */
1047 if (ip != GFS2_I(sdp->sd_rindex))
1048 error = gfs2_rindex_hold(sdp, &al->al_ri_gh);
1049 else if (!sdp->sd_rgrps) /* We may not have the rindex read
1050 in, so: */
1051 error = gfs2_ri_update(ip);
1052 if (error)
1053 return error;
1054 }
1055
1056try_again: 1045try_again:
1057 do { 1046 do {
1058 error = get_local_rgrp(ip, &last_unlinked); 1047 error = get_local_rgrp(ip, &last_unlinked);
@@ -1069,11 +1058,8 @@ try_again:
1069 } 1058 }
1070 } while (error && tries++ < 3); 1059 } while (error && tries++ < 3);
1071 1060
1072 if (error) { 1061 if (error)
1073 if (hold_rindex && ip != GFS2_I(sdp->sd_rindex))
1074 gfs2_glock_dq_uninit(&al->al_ri_gh);
1075 return error; 1062 return error;
1076 }
1077 1063
1078 /* no error, so we have the rgrp set in the inode's allocation. */ 1064 /* no error, so we have the rgrp set in the inode's allocation. */
1079 al->al_file = file; 1065 al->al_file = file;
@@ -1103,8 +1089,6 @@ void gfs2_inplace_release(struct gfs2_inode *ip)
1103 al->al_rgd = NULL; 1089 al->al_rgd = NULL;
1104 if (al->al_rgd_gh.gh_gl) 1090 if (al->al_rgd_gh.gh_gl)
1105 gfs2_glock_dq_uninit(&al->al_rgd_gh); 1091 gfs2_glock_dq_uninit(&al->al_rgd_gh);
1106 if (ip != GFS2_I(sdp->sd_rindex) && al->al_ri_gh.gh_gl)
1107 gfs2_glock_dq_uninit(&al->al_ri_gh);
1108} 1092}
1109 1093
1110/** 1094/**
@@ -1558,34 +1542,26 @@ void gfs2_free_di(struct gfs2_rgrpd *rgd, struct gfs2_inode *ip)
1558int gfs2_check_blk_type(struct gfs2_sbd *sdp, u64 no_addr, unsigned int type) 1542int gfs2_check_blk_type(struct gfs2_sbd *sdp, u64 no_addr, unsigned int type)
1559{ 1543{
1560 struct gfs2_rgrpd *rgd; 1544 struct gfs2_rgrpd *rgd;
1561 struct gfs2_holder ri_gh, rgd_gh; 1545 struct gfs2_holder rgd_gh;
1562 struct gfs2_inode *ip = GFS2_I(sdp->sd_rindex);
1563 int ri_locked = 0;
1564 int error; 1546 int error;
1565 1547
1566 if (!gfs2_glock_is_locked_by_me(ip->i_gl)) { 1548 error = gfs2_rindex_update(sdp);
1567 error = gfs2_rindex_hold(sdp, &ri_gh); 1549 if (error)
1568 if (error) 1550 return error;
1569 goto fail;
1570 ri_locked = 1;
1571 }
1572 1551
1573 error = -EINVAL; 1552 error = -EINVAL;
1574 rgd = gfs2_blk2rgrpd(sdp, no_addr); 1553 rgd = gfs2_blk2rgrpd(sdp, no_addr);
1575 if (!rgd) 1554 if (!rgd)
1576 goto fail_rindex; 1555 goto fail;
1577 1556
1578 error = gfs2_glock_nq_init(rgd->rd_gl, LM_ST_SHARED, 0, &rgd_gh); 1557 error = gfs2_glock_nq_init(rgd->rd_gl, LM_ST_SHARED, 0, &rgd_gh);
1579 if (error) 1558 if (error)
1580 goto fail_rindex; 1559 goto fail;
1581 1560
1582 if (gfs2_get_block_type(rgd, no_addr) != type) 1561 if (gfs2_get_block_type(rgd, no_addr) != type)
1583 error = -ESTALE; 1562 error = -ESTALE;
1584 1563
1585 gfs2_glock_dq_uninit(&rgd_gh); 1564 gfs2_glock_dq_uninit(&rgd_gh);
1586fail_rindex:
1587 if (ri_locked)
1588 gfs2_glock_dq_uninit(&ri_gh);
1589fail: 1565fail:
1590 return error; 1566 return error;
1591} 1567}