aboutsummaryrefslogtreecommitdiffstats
path: root/fs/gfs2/inode.c
diff options
context:
space:
mode:
authorBob Peterson <rpeterso@redhat.com>2012-07-19 08:12:40 -0400
committerSteven Whitehouse <swhiteho@redhat.com>2012-07-19 09:51:08 -0400
commit8e2e00473598dd5379d8408cb974dade000acafc (patch)
tree1f7bfdf0d07b6c0315bbd11ffee174742d66a459 /fs/gfs2/inode.c
parent294f2ad5a545eb71d397623743ddd8201131bdad (diff)
GFS2: Reduce file fragmentation
This patch reduces GFS2 file fragmentation by pre-reserving blocks. The resulting improved on disk layout greatly speeds up operations in cases which would have resulted in interlaced allocation of blocks previously. A typical example of this is 10 parallel dd processes, each writing to a file in a common dirctory. The implementation uses an rbtree of reservations attached to each resource group (and each inode). Signed-off-by: Bob Peterson <rpeterso@redhat.com> Signed-off-by: Steven Whitehouse <swhiteho@redhat.com>
Diffstat (limited to 'fs/gfs2/inode.c')
-rw-r--r--fs/gfs2/inode.c37
1 files changed, 28 insertions, 9 deletions
diff --git a/fs/gfs2/inode.c b/fs/gfs2/inode.c
index 2b035e0959b2..c53c67e30bd4 100644
--- a/fs/gfs2/inode.c
+++ b/fs/gfs2/inode.c
@@ -521,6 +521,9 @@ static int make_dinode(struct gfs2_inode *dip, struct gfs2_glock *gl,
521 int error; 521 int error;
522 522
523 munge_mode_uid_gid(dip, &mode, &uid, &gid); 523 munge_mode_uid_gid(dip, &mode, &uid, &gid);
524 error = gfs2_rindex_update(sdp);
525 if (error)
526 return error;
524 527
525 error = gfs2_quota_lock(dip, uid, gid); 528 error = gfs2_quota_lock(dip, uid, gid);
526 if (error) 529 if (error)
@@ -551,6 +554,10 @@ static int link_dinode(struct gfs2_inode *dip, const struct qstr *name,
551 struct buffer_head *dibh; 554 struct buffer_head *dibh;
552 int error; 555 int error;
553 556
557 error = gfs2_rindex_update(sdp);
558 if (error)
559 return error;
560
554 error = gfs2_quota_lock(dip, NO_QUOTA_CHANGE, NO_QUOTA_CHANGE); 561 error = gfs2_quota_lock(dip, NO_QUOTA_CHANGE, NO_QUOTA_CHANGE);
555 if (error) 562 if (error)
556 goto fail; 563 goto fail;
@@ -596,7 +603,8 @@ fail_end_trans:
596 gfs2_trans_end(sdp); 603 gfs2_trans_end(sdp);
597 604
598fail_ipreserv: 605fail_ipreserv:
599 gfs2_inplace_release(dip); 606 if (alloc_required)
607 gfs2_inplace_release(dip);
600 608
601fail_quota_locks: 609fail_quota_locks:
602 gfs2_quota_unlock(dip); 610 gfs2_quota_unlock(dip);
@@ -647,7 +655,7 @@ static int gfs2_create_inode(struct inode *dir, struct dentry *dentry,
647 const struct qstr *name = &dentry->d_name; 655 const struct qstr *name = &dentry->d_name;
648 struct gfs2_holder ghs[2]; 656 struct gfs2_holder ghs[2];
649 struct inode *inode = NULL; 657 struct inode *inode = NULL;
650 struct gfs2_inode *dip = GFS2_I(dir); 658 struct gfs2_inode *dip = GFS2_I(dir), *ip;
651 struct gfs2_sbd *sdp = GFS2_SB(&dip->i_inode); 659 struct gfs2_sbd *sdp = GFS2_SB(&dip->i_inode);
652 struct gfs2_inum_host inum = { .no_addr = 0, .no_formal_ino = 0 }; 660 struct gfs2_inum_host inum = { .no_addr = 0, .no_formal_ino = 0 };
653 int error; 661 int error;
@@ -657,6 +665,11 @@ static int gfs2_create_inode(struct inode *dir, struct dentry *dentry,
657 if (!name->len || name->len > GFS2_FNAMESIZE) 665 if (!name->len || name->len > GFS2_FNAMESIZE)
658 return -ENAMETOOLONG; 666 return -ENAMETOOLONG;
659 667
668 /* We need a reservation to allocate the new dinode block. The
669 directory ip temporarily points to the reservation, but this is
670 being done to get a set of contiguous blocks for the new dinode.
671 Since this is a create, we don't have a sizehint yet, so it will
672 have to use the minimum reservation size. */
660 error = gfs2_rs_alloc(dip); 673 error = gfs2_rs_alloc(dip);
661 if (error) 674 if (error)
662 return error; 675 return error;
@@ -694,24 +707,29 @@ static int gfs2_create_inode(struct inode *dir, struct dentry *dentry,
694 if (IS_ERR(inode)) 707 if (IS_ERR(inode))
695 goto fail_gunlock2; 708 goto fail_gunlock2;
696 709
697 error = gfs2_inode_refresh(GFS2_I(inode)); 710 ip = GFS2_I(inode);
711 error = gfs2_inode_refresh(ip);
698 if (error) 712 if (error)
699 goto fail_gunlock2; 713 goto fail_gunlock2;
700 714
701 /* the new inode needs a reservation so it can allocate xattrs. */ 715 /* The newly created inode needs a reservation so it can allocate
702 error = gfs2_rs_alloc(GFS2_I(inode)); 716 xattrs. At the same time, we want new blocks allocated to the new
703 if (error) 717 dinode to be as contiguous as possible. Since we allocated the
704 goto fail_gunlock2; 718 dinode block under the directory's reservation, we transfer
719 ownership of that reservation to the new inode. The directory
720 doesn't need a reservation unless it needs a new allocation. */
721 ip->i_res = dip->i_res;
722 dip->i_res = NULL;
705 723
706 error = gfs2_acl_create(dip, inode); 724 error = gfs2_acl_create(dip, inode);
707 if (error) 725 if (error)
708 goto fail_gunlock2; 726 goto fail_gunlock2;
709 727
710 error = gfs2_security_init(dip, GFS2_I(inode), name); 728 error = gfs2_security_init(dip, ip, name);
711 if (error) 729 if (error)
712 goto fail_gunlock2; 730 goto fail_gunlock2;
713 731
714 error = link_dinode(dip, name, GFS2_I(inode)); 732 error = link_dinode(dip, name, ip);
715 if (error) 733 if (error)
716 goto fail_gunlock2; 734 goto fail_gunlock2;
717 735
@@ -738,6 +756,7 @@ fail_gunlock:
738 iput(inode); 756 iput(inode);
739 } 757 }
740fail: 758fail:
759 gfs2_rs_delete(dip);
741 if (bh) 760 if (bh)
742 brelse(bh); 761 brelse(bh);
743 return error; 762 return error;