diff options
author | Barry Naujok <bnaujok@sgi.com> | 2008-05-21 02:58:22 -0400 |
---|---|---|
committer | Niv Sardi <xaiki@debian.org> | 2008-07-28 02:58:40 -0400 |
commit | 384f3ced07efdddf6838f6527366089d37843c94 (patch) | |
tree | 13037bc99115f6f940b6fe924b75dc48e0577678 /fs/xfs/xfs_vnodeops.c | |
parent | 9403540c0653122ca34884a180439ddbfcbcb524 (diff) |
[XFS] Return case-insensitive match for dentry cache
This implements the code to store the actual filename found during a
lookup in the dentry cache and to avoid multiple entries in the dcache
pointing to the same inode.
To avoid polluting the dcache, we implement a new directory inode
operations for lookup. xfs_vn_ci_lookup() stores the correct case name in
the dcache.
The "actual name" is only allocated and returned for a case- insensitive
match and not an actual match.
Another unusual interaction with the dcache is not storing negative
dentries like other filesystems doing a d_add(dentry, NULL) when an ENOENT
is returned. During the VFS lookup, if a dentry returned has no inode,
dput is called and ENOENT is returned. By not doing a d_add, this actually
removes it completely from the dcache to be reused. create/rename have to
be modified to support unhashed dentries being passed in.
SGI-PV: 981521
SGI-Modid: xfs-linux-melb:xfs-kern:31208a
Signed-off-by: Barry Naujok <bnaujok@sgi.com>
Signed-off-by: Christoph Hellwig <hch@infradead.org>
Diffstat (limited to 'fs/xfs/xfs_vnodeops.c')
-rw-r--r-- | fs/xfs/xfs_vnodeops.c | 19 |
1 files changed, 14 insertions, 5 deletions
diff --git a/fs/xfs/xfs_vnodeops.c b/fs/xfs/xfs_vnodeops.c index 9b8b87fcd4ec..b6a065eb25a5 100644 --- a/fs/xfs/xfs_vnodeops.c +++ b/fs/xfs/xfs_vnodeops.c | |||
@@ -1610,12 +1610,18 @@ xfs_inactive( | |||
1610 | return VN_INACTIVE_CACHE; | 1610 | return VN_INACTIVE_CACHE; |
1611 | } | 1611 | } |
1612 | 1612 | ||
1613 | 1613 | /* | |
1614 | * Lookups up an inode from "name". If ci_name is not NULL, then a CI match | ||
1615 | * is allowed, otherwise it has to be an exact match. If a CI match is found, | ||
1616 | * ci_name->name will point to a the actual name (caller must free) or | ||
1617 | * will be set to NULL if an exact match is found. | ||
1618 | */ | ||
1614 | int | 1619 | int |
1615 | xfs_lookup( | 1620 | xfs_lookup( |
1616 | xfs_inode_t *dp, | 1621 | xfs_inode_t *dp, |
1617 | struct xfs_name *name, | 1622 | struct xfs_name *name, |
1618 | xfs_inode_t **ipp) | 1623 | xfs_inode_t **ipp, |
1624 | struct xfs_name *ci_name) | ||
1619 | { | 1625 | { |
1620 | xfs_ino_t inum; | 1626 | xfs_ino_t inum; |
1621 | int error; | 1627 | int error; |
@@ -1627,7 +1633,7 @@ xfs_lookup( | |||
1627 | return XFS_ERROR(EIO); | 1633 | return XFS_ERROR(EIO); |
1628 | 1634 | ||
1629 | lock_mode = xfs_ilock_map_shared(dp); | 1635 | lock_mode = xfs_ilock_map_shared(dp); |
1630 | error = xfs_dir_lookup(NULL, dp, name, &inum); | 1636 | error = xfs_dir_lookup(NULL, dp, name, &inum, ci_name); |
1631 | xfs_iunlock_map_shared(dp, lock_mode); | 1637 | xfs_iunlock_map_shared(dp, lock_mode); |
1632 | 1638 | ||
1633 | if (error) | 1639 | if (error) |
@@ -1635,12 +1641,15 @@ xfs_lookup( | |||
1635 | 1641 | ||
1636 | error = xfs_iget(dp->i_mount, NULL, inum, 0, 0, ipp, 0); | 1642 | error = xfs_iget(dp->i_mount, NULL, inum, 0, 0, ipp, 0); |
1637 | if (error) | 1643 | if (error) |
1638 | goto out; | 1644 | goto out_free_name; |
1639 | 1645 | ||
1640 | xfs_itrace_ref(*ipp); | 1646 | xfs_itrace_ref(*ipp); |
1641 | return 0; | 1647 | return 0; |
1642 | 1648 | ||
1643 | out: | 1649 | out_free_name: |
1650 | if (ci_name) | ||
1651 | kmem_free(ci_name->name); | ||
1652 | out: | ||
1644 | *ipp = NULL; | 1653 | *ipp = NULL; |
1645 | return error; | 1654 | return error; |
1646 | } | 1655 | } |