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>
This commit is contained in:
parent
534cf9ca55
commit
2b47dad866
3 changed files with 42 additions and 16 deletions
|
@ -1659,26 +1659,34 @@ static int dir_new_leaf(struct inode *inode, const struct qstr *name)
|
|||
|
||||
/**
|
||||
* gfs2_dir_add - Add new filename into directory
|
||||
* @dip: The GFS2 inode
|
||||
* @filename: The new name
|
||||
* @inode: The inode number of the entry
|
||||
* @type: The type of the entry
|
||||
* @inode: The directory inode
|
||||
* @name: The new name
|
||||
* @nip: The GFS2 inode to be linked in to the directory
|
||||
* @da: The directory addition info
|
||||
*
|
||||
* If the call to gfs2_diradd_alloc_required resulted in there being
|
||||
* no need to allocate any new directory blocks, then it will contain
|
||||
* a pointer to the directory entry and the bh in which it resides. We
|
||||
* can use that without having to repeat the search. If there was no
|
||||
* free space, then we must now create more space.
|
||||
*
|
||||
* Returns: 0 on success, error code on failure
|
||||
*/
|
||||
|
||||
int gfs2_dir_add(struct inode *inode, const struct qstr *name,
|
||||
const struct gfs2_inode *nip)
|
||||
const struct gfs2_inode *nip, struct gfs2_diradd *da)
|
||||
{
|
||||
struct gfs2_inode *ip = GFS2_I(inode);
|
||||
struct buffer_head *bh;
|
||||
struct gfs2_dirent *dent;
|
||||
struct buffer_head *bh = da->bh;
|
||||
struct gfs2_dirent *dent = da->dent;
|
||||
struct gfs2_leaf *leaf;
|
||||
int error;
|
||||
|
||||
while(1) {
|
||||
dent = gfs2_dirent_search(inode, name, gfs2_dirent_find_space,
|
||||
&bh);
|
||||
if (da->bh == NULL) {
|
||||
dent = gfs2_dirent_search(inode, name,
|
||||
gfs2_dirent_find_space, &bh);
|
||||
}
|
||||
if (dent) {
|
||||
if (IS_ERR(dent))
|
||||
return PTR_ERR(dent);
|
||||
|
@ -1689,6 +1697,8 @@ int gfs2_dir_add(struct inode *inode, const struct qstr *name,
|
|||
leaf = (struct gfs2_leaf *)bh->b_data;
|
||||
be16_add_cpu(&leaf->lf_entries, 1);
|
||||
}
|
||||
da->dent = NULL;
|
||||
da->bh = NULL;
|
||||
brelse(bh);
|
||||
ip->i_entries++;
|
||||
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,
|
|||
struct buffer_head *bh;
|
||||
|
||||
da->nr_blocks = 0;
|
||||
da->bh = NULL;
|
||||
da->dent = NULL;
|
||||
|
||||
dent = gfs2_dirent_search(inode, name, gfs2_dirent_find_space, &bh);
|
||||
if (!dent) {
|
||||
|
@ -2038,7 +2050,8 @@ int gfs2_diradd_alloc_required(struct inode *inode, const struct qstr *name,
|
|||
}
|
||||
if (IS_ERR(dent))
|
||||
return PTR_ERR(dent);
|
||||
brelse(bh);
|
||||
da->bh = bh;
|
||||
da->dent = dent;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
|
@ -16,9 +16,13 @@
|
|||
struct inode;
|
||||
struct gfs2_inode;
|
||||
struct gfs2_inum;
|
||||
struct buffer_head;
|
||||
struct gfs2_dirent;
|
||||
|
||||
struct gfs2_diradd {
|
||||
unsigned nr_blocks;
|
||||
struct gfs2_dirent *dent;
|
||||
struct buffer_head *bh;
|
||||
};
|
||||
|
||||
extern struct inode *gfs2_dir_search(struct inode *dir,
|
||||
|
@ -27,7 +31,13 @@ extern struct inode *gfs2_dir_search(struct inode *dir,
|
|||
extern int gfs2_dir_check(struct inode *dir, const struct qstr *filename,
|
||||
const struct gfs2_inode *ip);
|
||||
extern int gfs2_dir_add(struct inode *inode, const struct qstr *filename,
|
||||
const struct gfs2_inode *ip);
|
||||
const struct gfs2_inode *ip, struct gfs2_diradd *da);
|
||||
static inline void gfs2_dir_no_add(struct gfs2_diradd *da)
|
||||
{
|
||||
if (da->bh)
|
||||
brelse(da->bh);
|
||||
da->bh = NULL;
|
||||
}
|
||||
extern int gfs2_dir_del(struct gfs2_inode *dip, const struct dentry *dentry);
|
||||
extern int gfs2_dir_read(struct inode *inode, struct dir_context *ctx,
|
||||
struct file_ra_state *f_ra);
|
||||
|
|
|
@ -516,7 +516,7 @@ static int link_dinode(struct gfs2_inode *dip, const struct qstr *name,
|
|||
goto fail_quota_locks;
|
||||
}
|
||||
|
||||
error = gfs2_dir_add(&dip->i_inode, name, ip);
|
||||
error = gfs2_dir_add(&dip->i_inode, name, ip, da);
|
||||
if (error)
|
||||
goto fail_end_trans;
|
||||
|
||||
|
@ -579,7 +579,7 @@ static int gfs2_create_inode(struct inode *dir, struct dentry *dentry,
|
|||
struct dentry *d;
|
||||
int error;
|
||||
u32 aflags = 0;
|
||||
struct gfs2_diradd da;
|
||||
struct gfs2_diradd da = { .bh = NULL, };
|
||||
|
||||
if (!name->len || name->len > GFS2_FNAMESIZE)
|
||||
return -ENAMETOOLONG;
|
||||
|
@ -738,6 +738,7 @@ static int gfs2_create_inode(struct inode *dir, struct dentry *dentry,
|
|||
free_inode_nonrcu(inode);
|
||||
inode = NULL;
|
||||
fail_gunlock:
|
||||
gfs2_dir_no_add(&da);
|
||||
gfs2_glock_dq_uninit(ghs);
|
||||
if (inode && !IS_ERR(inode)) {
|
||||
clear_nlink(inode);
|
||||
|
@ -836,7 +837,7 @@ static int gfs2_link(struct dentry *old_dentry, struct inode *dir,
|
|||
struct gfs2_inode *ip = GFS2_I(inode);
|
||||
struct gfs2_holder ghs[2];
|
||||
struct buffer_head *dibh;
|
||||
struct gfs2_diradd da;
|
||||
struct gfs2_diradd da = { .bh = NULL, };
|
||||
int error;
|
||||
|
||||
if (S_ISDIR(inode->i_mode))
|
||||
|
@ -918,7 +919,7 @@ static int gfs2_link(struct dentry *old_dentry, struct inode *dir,
|
|||
if (error)
|
||||
goto out_end_trans;
|
||||
|
||||
error = gfs2_dir_add(dir, &dentry->d_name, ip);
|
||||
error = gfs2_dir_add(dir, &dentry->d_name, ip, &da);
|
||||
if (error)
|
||||
goto out_brelse;
|
||||
|
||||
|
@ -940,6 +941,7 @@ static int gfs2_link(struct dentry *old_dentry, struct inode *dir,
|
|||
if (da.nr_blocks)
|
||||
gfs2_quota_unlock(dip);
|
||||
out_gunlock:
|
||||
gfs2_dir_no_add(&da);
|
||||
gfs2_glock_dq(ghs + 1);
|
||||
out_child:
|
||||
gfs2_glock_dq(ghs);
|
||||
|
@ -1454,7 +1456,7 @@ static int gfs2_rename(struct inode *odir, struct dentry *odentry,
|
|||
if (error)
|
||||
goto out_end_trans;
|
||||
|
||||
error = gfs2_dir_add(ndir, &ndentry->d_name, ip);
|
||||
error = gfs2_dir_add(ndir, &ndentry->d_name, ip, &da);
|
||||
if (error)
|
||||
goto out_end_trans;
|
||||
|
||||
|
@ -1467,6 +1469,7 @@ static int gfs2_rename(struct inode *odir, struct dentry *odentry,
|
|||
if (da.nr_blocks)
|
||||
gfs2_quota_unlock(ndip);
|
||||
out_gunlock:
|
||||
gfs2_dir_no_add(&da);
|
||||
while (x--) {
|
||||
gfs2_glock_dq(ghs + x);
|
||||
gfs2_holder_uninit(ghs + x);
|
||||
|
|
Loading…
Reference in a new issue