diff options
author | Steven Whitehouse <swhiteho@redhat.com> | 2014-01-06 07:49:43 -0500 |
---|---|---|
committer | Steven Whitehouse <swhiteho@redhat.com> | 2014-01-06 07:49:43 -0500 |
commit | 2b47dad866d04f14c328f888ba5406057b8c7d33 (patch) | |
tree | 9eb66c086c2e49080234e0a9a1014624354ebea3 | |
parent | 534cf9ca553953e4c12fa5f0d23e543f9a6ccbaf (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.c | 33 | ||||
-rw-r--r-- | fs/gfs2/dir.h | 12 | ||||
-rw-r--r-- | fs/gfs2/inode.c | 13 |
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 | ||
1670 | int gfs2_dir_add(struct inode *inode, const struct qstr *name, | 1676 | int 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 @@ | |||
16 | struct inode; | 16 | struct inode; |
17 | struct gfs2_inode; | 17 | struct gfs2_inode; |
18 | struct gfs2_inum; | 18 | struct gfs2_inum; |
19 | struct buffer_head; | ||
20 | struct gfs2_dirent; | ||
19 | 21 | ||
20 | struct gfs2_diradd { | 22 | struct gfs2_diradd { |
21 | unsigned nr_blocks; | 23 | unsigned nr_blocks; |
24 | struct gfs2_dirent *dent; | ||
25 | struct buffer_head *bh; | ||
22 | }; | 26 | }; |
23 | 27 | ||
24 | extern struct inode *gfs2_dir_search(struct inode *dir, | 28 | extern struct inode *gfs2_dir_search(struct inode *dir, |
@@ -27,7 +31,13 @@ extern struct inode *gfs2_dir_search(struct inode *dir, | |||
27 | extern int gfs2_dir_check(struct inode *dir, const struct qstr *filename, | 31 | extern int gfs2_dir_check(struct inode *dir, const struct qstr *filename, |
28 | const struct gfs2_inode *ip); | 32 | const struct gfs2_inode *ip); |
29 | extern int gfs2_dir_add(struct inode *inode, const struct qstr *filename, | 33 | extern 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); |
35 | static inline void gfs2_dir_no_add(struct gfs2_diradd *da) | ||
36 | { | ||
37 | if (da->bh) | ||
38 | brelse(da->bh); | ||
39 | da->bh = NULL; | ||
40 | } | ||
31 | extern int gfs2_dir_del(struct gfs2_inode *dip, const struct dentry *dentry); | 41 | extern int gfs2_dir_del(struct gfs2_inode *dip, const struct dentry *dentry); |
32 | extern int gfs2_dir_read(struct inode *inode, struct dir_context *ctx, | 42 | extern 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; |
740 | fail_gunlock: | 740 | fail_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); |
942 | out_gunlock: | 943 | out_gunlock: |
944 | gfs2_dir_no_add(&da); | ||
943 | gfs2_glock_dq(ghs + 1); | 945 | gfs2_glock_dq(ghs + 1); |
944 | out_child: | 946 | out_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); |
1469 | out_gunlock: | 1471 | out_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); |