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_dir2_sf.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_dir2_sf.c')
-rw-r--r-- | fs/xfs/xfs_dir2_sf.c | 17 |
1 files changed, 10 insertions, 7 deletions
diff --git a/fs/xfs/xfs_dir2_sf.c b/fs/xfs/xfs_dir2_sf.c index 9409fd3e565f..b46af0013ec9 100644 --- a/fs/xfs/xfs_dir2_sf.c +++ b/fs/xfs/xfs_dir2_sf.c | |||
@@ -812,9 +812,11 @@ xfs_dir2_sf_lookup( | |||
812 | { | 812 | { |
813 | xfs_inode_t *dp; /* incore directory inode */ | 813 | xfs_inode_t *dp; /* incore directory inode */ |
814 | int i; /* entry index */ | 814 | int i; /* entry index */ |
815 | int error; | ||
815 | xfs_dir2_sf_entry_t *sfep; /* shortform directory entry */ | 816 | xfs_dir2_sf_entry_t *sfep; /* shortform directory entry */ |
816 | xfs_dir2_sf_t *sfp; /* shortform structure */ | 817 | xfs_dir2_sf_t *sfp; /* shortform structure */ |
817 | enum xfs_dacmp cmp; /* comparison result */ | 818 | enum xfs_dacmp cmp; /* comparison result */ |
819 | xfs_dir2_sf_entry_t *ci_sfep; /* case-insens. entry */ | ||
818 | 820 | ||
819 | xfs_dir2_trace_args("sf_lookup", args); | 821 | xfs_dir2_trace_args("sf_lookup", args); |
820 | xfs_dir2_sf_check(args); | 822 | xfs_dir2_sf_check(args); |
@@ -852,6 +854,7 @@ xfs_dir2_sf_lookup( | |||
852 | /* | 854 | /* |
853 | * Loop over all the entries trying to match ours. | 855 | * Loop over all the entries trying to match ours. |
854 | */ | 856 | */ |
857 | ci_sfep = NULL; | ||
855 | for (i = 0, sfep = xfs_dir2_sf_firstentry(sfp); i < sfp->hdr.count; | 858 | for (i = 0, sfep = xfs_dir2_sf_firstentry(sfp); i < sfp->hdr.count; |
856 | i++, sfep = xfs_dir2_sf_nextentry(sfp, sfep)) { | 859 | i++, sfep = xfs_dir2_sf_nextentry(sfp, sfep)) { |
857 | /* | 860 | /* |
@@ -867,19 +870,19 @@ xfs_dir2_sf_lookup( | |||
867 | xfs_dir2_sf_inumberp(sfep)); | 870 | xfs_dir2_sf_inumberp(sfep)); |
868 | if (cmp == XFS_CMP_EXACT) | 871 | if (cmp == XFS_CMP_EXACT) |
869 | return XFS_ERROR(EEXIST); | 872 | return XFS_ERROR(EEXIST); |
873 | ci_sfep = sfep; | ||
870 | } | 874 | } |
871 | } | 875 | } |
872 | ASSERT(args->op_flags & XFS_DA_OP_OKNOENT); | 876 | ASSERT(args->op_flags & XFS_DA_OP_OKNOENT); |
873 | /* | 877 | /* |
874 | * Here, we can only be doing a lookup (not a rename or replace). | 878 | * Here, we can only be doing a lookup (not a rename or replace). |
875 | * If a case-insensitive match was found earlier, return "found". | 879 | * If a case-insensitive match was not found, return ENOENT. |
876 | */ | 880 | */ |
877 | if (args->cmpresult == XFS_CMP_CASE) | 881 | if (!ci_sfep) |
878 | return XFS_ERROR(EEXIST); | 882 | return XFS_ERROR(ENOENT); |
879 | /* | 883 | /* otherwise process the CI match as required by the caller */ |
880 | * Didn't find it. | 884 | error = xfs_dir_cilookup_result(args, ci_sfep->name, ci_sfep->namelen); |
881 | */ | 885 | return XFS_ERROR(error); |
882 | return XFS_ERROR(ENOENT); | ||
883 | } | 886 | } |
884 | 887 | ||
885 | /* | 888 | /* |