diff options
author | Steven Whitehouse <swhiteho@redhat.com> | 2013-06-11 08:45:29 -0400 |
---|---|---|
committer | Steven Whitehouse <swhiteho@redhat.com> | 2013-06-11 08:45:29 -0400 |
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, | |||
313 | goto out; | 313 | goto out; |
314 | } | 314 | } |
315 | 315 | ||
316 | inode = gfs2_dir_search(dir, name); | 316 | inode = gfs2_dir_search(dir, name, false); |
317 | if (IS_ERR(inode)) | 317 | if (IS_ERR(inode)) |
318 | error = PTR_ERR(inode); | 318 | error = PTR_ERR(inode); |
319 | out: | 319 | out: |
@@ -346,17 +346,6 @@ static int create_ok(struct gfs2_inode *dip, const struct qstr *name, | |||
346 | if (!dip->i_inode.i_nlink) | 346 | if (!dip->i_inode.i_nlink) |
347 | return -ENOENT; | 347 | return -ENOENT; |
348 | 348 | ||
349 | error = gfs2_dir_check(&dip->i_inode, name, NULL); | ||
350 | switch (error) { | ||
351 | case -ENOENT: | ||
352 | error = 0; | ||
353 | break; | ||
354 | case 0: | ||
355 | return -EEXIST; | ||
356 | default: | ||
357 | return error; | ||
358 | } | ||
359 | |||
360 | if (dip->i_entries == (u32)-1) | 349 | if (dip->i_entries == (u32)-1) |
361 | return -EFBIG; | 350 | return -EFBIG; |
362 | if (S_ISDIR(mode) && dip->i_inode.i_nlink == (u32)-1) | 351 | 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, | |||
584 | goto fail; | 573 | goto fail; |
585 | 574 | ||
586 | error = create_ok(dip, name, mode); | 575 | error = create_ok(dip, name, mode); |
587 | if ((error == -EEXIST) && S_ISREG(mode) && !excl) { | 576 | if (error) |
588 | inode = gfs2_lookupi(dir, &dentry->d_name, 0); | 577 | goto fail_gunlock; |
578 | |||
579 | inode = gfs2_dir_search(dir, &dentry->d_name, !S_ISREG(mode) || excl); | ||
580 | error = PTR_ERR(inode); | ||
581 | if (!IS_ERR(inode)) { | ||
589 | gfs2_glock_dq_uninit(ghs); | 582 | gfs2_glock_dq_uninit(ghs); |
590 | d_instantiate(dentry, inode); | 583 | d_instantiate(dentry, inode); |
591 | return PTR_RET(inode); | 584 | return 0; |
592 | } | 585 | } else if (error != -ENOENT) { |
593 | if (error) | ||
594 | goto fail_gunlock; | 586 | goto fail_gunlock; |
587 | } | ||
595 | 588 | ||
596 | arq = error = gfs2_diradd_alloc_required(dir, name); | 589 | arq = error = gfs2_diradd_alloc_required(dir, name); |
597 | if (error < 0) | 590 | if (error < 0) |