diff options
author | Steven Whitehouse <swhiteho@redhat.com> | 2013-06-11 13:45:29 +0100 |
---|---|---|
committer | Steven Whitehouse <swhiteho@redhat.com> | 2013-06-11 13:45:29 +0100 |
commit | 5a00f3cc978be45b9d2597851bedaa40630bc597 (patch) | |
tree | 716a1b29594e352c4c793b699331d4d57578cce9 /fs/gfs2/inode.c | |
parent | a9aefd707c65aa5a7945b3f16bd39f314aa8414d (diff) |
GFS2: Only do one directory search on create
Creation of a new inode requires a directory search in order to ensure
that we are not trying to create an inode with the same name as an
existing one. This was hidden away inside the create_ok() function.
In the case that there was an existing inode, and a lookup can be
substituted for a create (which is the case with regular files
when the O_EXCL flag is not in use) then we were doing a second
lookup in order to return the inode.
This patch merges these two lookups into one. This can be done by
passing a flag to gfs2_dir_search() to tell it to just return -EEXIST
in the cases where we don't actually want to look up the inode.
Signed-off-by: Steven Whitehouse <swhiteho@redhat.com>
Diffstat (limited to 'fs/gfs2/inode.c')
-rw-r--r-- | fs/gfs2/inode.c | 27 |
1 files changed, 10 insertions, 17 deletions
diff --git a/fs/gfs2/inode.c b/fs/gfs2/inode.c index 5fbb8dfb4653..ede16ae784e2 100644 --- a/fs/gfs2/inode.c +++ b/fs/gfs2/inode.c @@ -313,7 +313,7 @@ struct inode *gfs2_lookupi(struct inode *dir, const struct qstr *name, goto out; } - inode = gfs2_dir_search(dir, name); + inode = gfs2_dir_search(dir, name, false); if (IS_ERR(inode)) error = PTR_ERR(inode); out: @@ -346,17 +346,6 @@ static int create_ok(struct gfs2_inode *dip, const struct qstr *name, if (!dip->i_inode.i_nlink) return -ENOENT; - error = gfs2_dir_check(&dip->i_inode, name, NULL); - switch (error) { - case -ENOENT: - error = 0; - break; - case 0: - return -EEXIST; - default: - return error; - } - if (dip->i_entries == (u32)-1) return -EFBIG; if (S_ISDIR(mode) && dip->i_inode.i_nlink == (u32)-1) @@ -584,14 +573,18 @@ static int gfs2_create_inode(struct inode *dir, struct dentry *dentry, goto fail; error = create_ok(dip, name, mode); - if ((error == -EEXIST) && S_ISREG(mode) && !excl) { - inode = gfs2_lookupi(dir, &dentry->d_name, 0); + if (error) + goto fail_gunlock; + + inode = gfs2_dir_search(dir, &dentry->d_name, !S_ISREG(mode) || excl); + error = PTR_ERR(inode); + if (!IS_ERR(inode)) { gfs2_glock_dq_uninit(ghs); d_instantiate(dentry, inode); - return PTR_RET(inode); - } - if (error) + return 0; + } else if (error != -ENOENT) { goto fail_gunlock; + } arq = error = gfs2_diradd_alloc_required(dir, name); if (error < 0) |