aboutsummaryrefslogtreecommitdiffstats
path: root/fs/gfs2/dir.c
diff options
context:
space:
mode:
authorSteven Whitehouse <swhiteho@redhat.com>2013-06-11 08:45:29 -0400
committerSteven Whitehouse <swhiteho@redhat.com>2013-06-11 08:45:29 -0400
commit5a00f3cc978be45b9d2597851bedaa40630bc597 (patch)
tree716a1b29594e352c4c793b699331d4d57578cce9 /fs/gfs2/dir.c
parenta9aefd707c65aa5a7945b3f16bd39f314aa8414d (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/dir.c')
-rw-r--r--fs/gfs2/dir.c23
1 files changed, 13 insertions, 10 deletions
diff --git a/fs/gfs2/dir.c b/fs/gfs2/dir.c
index b631c9043460..f0c70529948f 100644
--- a/fs/gfs2/dir.c
+++ b/fs/gfs2/dir.c
@@ -1555,9 +1555,9 @@ out:
1555 1555
1556/** 1556/**
1557 * gfs2_dir_search - Search a directory 1557 * gfs2_dir_search - Search a directory
1558 * @dip: The GFS2 inode 1558 * @dip: The GFS2 dir inode
1559 * @filename: 1559 * @name: The name we are looking up
1560 * @inode: 1560 * @fail_on_exist: Fail if the name exists rather than looking it up
1561 * 1561 *
1562 * This routine searches a directory for a file or another directory. 1562 * This routine searches a directory for a file or another directory.
1563 * Assumes a glock is held on dip. 1563 * Assumes a glock is held on dip.
@@ -1565,22 +1565,25 @@ out:
1565 * Returns: errno 1565 * Returns: errno
1566 */ 1566 */
1567 1567
1568struct inode *gfs2_dir_search(struct inode *dir, const struct qstr *name) 1568struct inode *gfs2_dir_search(struct inode *dir, const struct qstr *name,
1569 bool fail_on_exist)
1569{ 1570{
1570 struct buffer_head *bh; 1571 struct buffer_head *bh;
1571 struct gfs2_dirent *dent; 1572 struct gfs2_dirent *dent;
1572 struct inode *inode; 1573 u64 addr, formal_ino;
1574 u16 dtype;
1573 1575
1574 dent = gfs2_dirent_search(dir, name, gfs2_dirent_find, &bh); 1576 dent = gfs2_dirent_search(dir, name, gfs2_dirent_find, &bh);
1575 if (dent) { 1577 if (dent) {
1576 if (IS_ERR(dent)) 1578 if (IS_ERR(dent))
1577 return ERR_CAST(dent); 1579 return ERR_CAST(dent);
1578 inode = gfs2_inode_lookup(dir->i_sb, 1580 dtype = be16_to_cpu(dent->de_type);
1579 be16_to_cpu(dent->de_type), 1581 addr = be64_to_cpu(dent->de_inum.no_addr);
1580 be64_to_cpu(dent->de_inum.no_addr), 1582 formal_ino = be64_to_cpu(dent->de_inum.no_formal_ino);
1581 be64_to_cpu(dent->de_inum.no_formal_ino), 0);
1582 brelse(bh); 1583 brelse(bh);
1583 return inode; 1584 if (fail_on_exist)
1585 return ERR_PTR(-EEXIST);
1586 return gfs2_inode_lookup(dir->i_sb, dtype, addr, formal_ino, 0);
1584 } 1587 }
1585 return ERR_PTR(-ENOENT); 1588 return ERR_PTR(-ENOENT);
1586} 1589}