summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSteven Whitehouse <swhiteho@redhat.com>2014-01-06 07:49:43 -0500
committerSteven Whitehouse <swhiteho@redhat.com>2014-01-06 07:49:43 -0500
commit2b47dad866d04f14c328f888ba5406057b8c7d33 (patch)
tree9eb66c086c2e49080234e0a9a1014624354ebea3
parent534cf9ca553953e4c12fa5f0d23e543f9a6ccbaf (diff)
GFS2: Remember directory insert point
When we look to see if there is enough space to add a dir entry without allocation, we have then been repeating the same search later when we do the actual insertion. This patch caches the details of the location in the gfs2_diradd structure, so that we do not have to repeat the search. This will provide a performance improvement which will be greater as the size of the directory increases. Signed-off-by: Steven Whitehouse <swhiteho@redhat.com>
-rw-r--r--fs/gfs2/dir.c33
-rw-r--r--fs/gfs2/dir.h12
-rw-r--r--fs/gfs2/inode.c13
3 files changed, 42 insertions, 16 deletions
diff --git a/fs/gfs2/dir.c b/fs/gfs2/dir.c
index 0b6be202a82c..d5988aafaa74 100644
--- a/fs/gfs2/dir.c
+++ b/fs/gfs2/dir.c
@@ -1659,26 +1659,34 @@ static int dir_new_leaf(struct inode *inode, const struct qstr *name)
1659 1659
1660/** 1660/**
1661 * gfs2_dir_add - Add new filename into directory 1661 * gfs2_dir_add - Add new filename into directory
1662 * @dip: The GFS2 inode 1662 * @inode: The directory inode
1663 * @filename: The new name 1663 * @name: The new name
1664 * @inode: The inode number of the entry 1664 * @nip: The GFS2 inode to be linked in to the directory
1665 * @type: The type of the entry 1665 * @da: The directory addition info
1666 *
1667 * If the call to gfs2_diradd_alloc_required resulted in there being
1668 * no need to allocate any new directory blocks, then it will contain
1669 * a pointer to the directory entry and the bh in which it resides. We
1670 * can use that without having to repeat the search. If there was no
1671 * free space, then we must now create more space.
1666 * 1672 *
1667 * Returns: 0 on success, error code on failure 1673 * Returns: 0 on success, error code on failure
1668 */ 1674 */
1669 1675
1670int gfs2_dir_add(struct inode *inode, const struct qstr *name, 1676int gfs2_dir_add(struct inode *inode, const struct qstr *name,
1671 const struct gfs2_inode *nip) 1677 const struct gfs2_inode *nip, struct gfs2_diradd *da)
1672{ 1678{
1673 struct gfs2_inode *ip = GFS2_I(inode); 1679 struct gfs2_inode *ip = GFS2_I(inode);
1674 struct buffer_head *bh; 1680 struct buffer_head *bh = da->bh;
1675 struct gfs2_dirent *dent; 1681 struct gfs2_dirent *dent = da->dent;
1676 struct gfs2_leaf *leaf; 1682 struct gfs2_leaf *leaf;
1677 int error; 1683 int error;
1678 1684
1679 while(1) { 1685 while(1) {
1680 dent = gfs2_dirent_search(inode, name, gfs2_dirent_find_space, 1686 if (da->bh == NULL) {
1681 &bh); 1687 dent = gfs2_dirent_search(inode, name,
1688 gfs2_dirent_find_space, &bh);
1689 }
1682 if (dent) { 1690 if (dent) {
1683 if (IS_ERR(dent)) 1691 if (IS_ERR(dent))
1684 return PTR_ERR(dent); 1692 return PTR_ERR(dent);
@@ -1689,6 +1697,8 @@ int gfs2_dir_add(struct inode *inode, const struct qstr *name,
1689 leaf = (struct gfs2_leaf *)bh->b_data; 1697 leaf = (struct gfs2_leaf *)bh->b_data;
1690 be16_add_cpu(&leaf->lf_entries, 1); 1698 be16_add_cpu(&leaf->lf_entries, 1);
1691 } 1699 }
1700 da->dent = NULL;
1701 da->bh = NULL;
1692 brelse(bh); 1702 brelse(bh);
1693 ip->i_entries++; 1703 ip->i_entries++;
1694 ip->i_inode.i_mtime = ip->i_inode.i_ctime = CURRENT_TIME; 1704 ip->i_inode.i_mtime = ip->i_inode.i_ctime = CURRENT_TIME;
@@ -2030,6 +2040,8 @@ int gfs2_diradd_alloc_required(struct inode *inode, const struct qstr *name,
2030 struct buffer_head *bh; 2040 struct buffer_head *bh;
2031 2041
2032 da->nr_blocks = 0; 2042 da->nr_blocks = 0;
2043 da->bh = NULL;
2044 da->dent = NULL;
2033 2045
2034 dent = gfs2_dirent_search(inode, name, gfs2_dirent_find_space, &bh); 2046 dent = gfs2_dirent_search(inode, name, gfs2_dirent_find_space, &bh);
2035 if (!dent) { 2047 if (!dent) {
@@ -2038,7 +2050,8 @@ int gfs2_diradd_alloc_required(struct inode *inode, const struct qstr *name,
2038 } 2050 }
2039 if (IS_ERR(dent)) 2051 if (IS_ERR(dent))
2040 return PTR_ERR(dent); 2052 return PTR_ERR(dent);
2041 brelse(bh); 2053 da->bh = bh;
2054 da->dent = dent;
2042 return 0; 2055 return 0;
2043} 2056}
2044 2057
diff --git a/fs/gfs2/dir.h b/fs/gfs2/dir.h
index c5573e703a7a..126c65dda028 100644
--- a/fs/gfs2/dir.h
+++ b/fs/gfs2/dir.h
@@ -16,9 +16,13 @@
16struct inode; 16struct inode;
17struct gfs2_inode; 17struct gfs2_inode;
18struct gfs2_inum; 18struct gfs2_inum;
19struct buffer_head;
20struct gfs2_dirent;
19 21
20struct gfs2_diradd { 22struct gfs2_diradd {
21 unsigned nr_blocks; 23 unsigned nr_blocks;
24 struct gfs2_dirent *dent;
25 struct buffer_head *bh;
22}; 26};
23 27
24extern struct inode *gfs2_dir_search(struct inode *dir, 28extern struct inode *gfs2_dir_search(struct inode *dir,
@@ -27,7 +31,13 @@ extern struct inode *gfs2_dir_search(struct inode *dir,
27extern int gfs2_dir_check(struct inode *dir, const struct qstr *filename, 31extern int gfs2_dir_check(struct inode *dir, const struct qstr *filename,
28 const struct gfs2_inode *ip); 32 const struct gfs2_inode *ip);
29extern int gfs2_dir_add(struct inode *inode, const struct qstr *filename, 33extern int gfs2_dir_add(struct inode *inode, const struct qstr *filename,
30 const struct gfs2_inode *ip); 34 const struct gfs2_inode *ip, struct gfs2_diradd *da);
35static inline void gfs2_dir_no_add(struct gfs2_diradd *da)
36{
37 if (da->bh)
38 brelse(da->bh);
39 da->bh = NULL;
40}
31extern int gfs2_dir_del(struct gfs2_inode *dip, const struct dentry *dentry); 41extern int gfs2_dir_del(struct gfs2_inode *dip, const struct dentry *dentry);
32extern int gfs2_dir_read(struct inode *inode, struct dir_context *ctx, 42extern int gfs2_dir_read(struct inode *inode, struct dir_context *ctx,
33 struct file_ra_state *f_ra); 43 struct file_ra_state *f_ra);
diff --git a/fs/gfs2/inode.c b/fs/gfs2/inode.c
index fa4624feef0f..4acc584038ee 100644
--- a/fs/gfs2/inode.c
+++ b/fs/gfs2/inode.c
@@ -516,7 +516,7 @@ static int link_dinode(struct gfs2_inode *dip, const struct qstr *name,
516 goto fail_quota_locks; 516 goto fail_quota_locks;
517 } 517 }
518 518
519 error = gfs2_dir_add(&dip->i_inode, name, ip); 519 error = gfs2_dir_add(&dip->i_inode, name, ip, da);
520 if (error) 520 if (error)
521 goto fail_end_trans; 521 goto fail_end_trans;
522 522
@@ -579,7 +579,7 @@ static int gfs2_create_inode(struct inode *dir, struct dentry *dentry,
579 struct dentry *d; 579 struct dentry *d;
580 int error; 580 int error;
581 u32 aflags = 0; 581 u32 aflags = 0;
582 struct gfs2_diradd da; 582 struct gfs2_diradd da = { .bh = NULL, };
583 583
584 if (!name->len || name->len > GFS2_FNAMESIZE) 584 if (!name->len || name->len > GFS2_FNAMESIZE)
585 return -ENAMETOOLONG; 585 return -ENAMETOOLONG;
@@ -738,6 +738,7 @@ fail_free_inode:
738 free_inode_nonrcu(inode); 738 free_inode_nonrcu(inode);
739 inode = NULL; 739 inode = NULL;
740fail_gunlock: 740fail_gunlock:
741 gfs2_dir_no_add(&da);
741 gfs2_glock_dq_uninit(ghs); 742 gfs2_glock_dq_uninit(ghs);
742 if (inode && !IS_ERR(inode)) { 743 if (inode && !IS_ERR(inode)) {
743 clear_nlink(inode); 744 clear_nlink(inode);
@@ -836,7 +837,7 @@ static int gfs2_link(struct dentry *old_dentry, struct inode *dir,
836 struct gfs2_inode *ip = GFS2_I(inode); 837 struct gfs2_inode *ip = GFS2_I(inode);
837 struct gfs2_holder ghs[2]; 838 struct gfs2_holder ghs[2];
838 struct buffer_head *dibh; 839 struct buffer_head *dibh;
839 struct gfs2_diradd da; 840 struct gfs2_diradd da = { .bh = NULL, };
840 int error; 841 int error;
841 842
842 if (S_ISDIR(inode->i_mode)) 843 if (S_ISDIR(inode->i_mode))
@@ -918,7 +919,7 @@ static int gfs2_link(struct dentry *old_dentry, struct inode *dir,
918 if (error) 919 if (error)
919 goto out_end_trans; 920 goto out_end_trans;
920 921
921 error = gfs2_dir_add(dir, &dentry->d_name, ip); 922 error = gfs2_dir_add(dir, &dentry->d_name, ip, &da);
922 if (error) 923 if (error)
923 goto out_brelse; 924 goto out_brelse;
924 925
@@ -940,6 +941,7 @@ out_gunlock_q:
940 if (da.nr_blocks) 941 if (da.nr_blocks)
941 gfs2_quota_unlock(dip); 942 gfs2_quota_unlock(dip);
942out_gunlock: 943out_gunlock:
944 gfs2_dir_no_add(&da);
943 gfs2_glock_dq(ghs + 1); 945 gfs2_glock_dq(ghs + 1);
944out_child: 946out_child:
945 gfs2_glock_dq(ghs); 947 gfs2_glock_dq(ghs);
@@ -1454,7 +1456,7 @@ static int gfs2_rename(struct inode *odir, struct dentry *odentry,
1454 if (error) 1456 if (error)
1455 goto out_end_trans; 1457 goto out_end_trans;
1456 1458
1457 error = gfs2_dir_add(ndir, &ndentry->d_name, ip); 1459 error = gfs2_dir_add(ndir, &ndentry->d_name, ip, &da);
1458 if (error) 1460 if (error)
1459 goto out_end_trans; 1461 goto out_end_trans;
1460 1462
@@ -1467,6 +1469,7 @@ out_gunlock_q:
1467 if (da.nr_blocks) 1469 if (da.nr_blocks)
1468 gfs2_quota_unlock(ndip); 1470 gfs2_quota_unlock(ndip);
1469out_gunlock: 1471out_gunlock:
1472 gfs2_dir_no_add(&da);
1470 while (x--) { 1473 while (x--) {
1471 gfs2_glock_dq(ghs + x); 1474 gfs2_glock_dq(ghs + x);
1472 gfs2_holder_uninit(ghs + x); 1475 gfs2_holder_uninit(ghs + x);