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_node.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_node.c')
-rw-r--r-- | fs/xfs/xfs_dir2_node.c | 16 |
1 files changed, 11 insertions, 5 deletions
diff --git a/fs/xfs/xfs_dir2_node.c b/fs/xfs/xfs_dir2_node.c index c71cff85950c..1b5430223461 100644 --- a/fs/xfs/xfs_dir2_node.c +++ b/fs/xfs/xfs_dir2_node.c | |||
@@ -549,7 +549,7 @@ xfs_dir2_leafn_lookup_for_entry( | |||
549 | xfs_dir2_data_entry_t *dep; /* data block entry */ | 549 | xfs_dir2_data_entry_t *dep; /* data block entry */ |
550 | xfs_inode_t *dp; /* incore directory inode */ | 550 | xfs_inode_t *dp; /* incore directory inode */ |
551 | int error; /* error return value */ | 551 | int error; /* error return value */ |
552 | int di; /* data entry index */ | 552 | int di = -1; /* data entry index */ |
553 | int index; /* leaf entry index */ | 553 | int index; /* leaf entry index */ |
554 | xfs_dir2_leaf_t *leaf; /* leaf structure */ | 554 | xfs_dir2_leaf_t *leaf; /* leaf structure */ |
555 | xfs_dir2_leaf_entry_t *lep; /* leaf entry */ | 555 | xfs_dir2_leaf_entry_t *lep; /* leaf entry */ |
@@ -577,6 +577,7 @@ xfs_dir2_leafn_lookup_for_entry( | |||
577 | if (state->extravalid) { | 577 | if (state->extravalid) { |
578 | curbp = state->extrablk.bp; | 578 | curbp = state->extrablk.bp; |
579 | curdb = state->extrablk.blkno; | 579 | curdb = state->extrablk.blkno; |
580 | di = state->extrablk.index; | ||
580 | } | 581 | } |
581 | /* | 582 | /* |
582 | * Loop over leaf entries with the right hash value. | 583 | * Loop over leaf entries with the right hash value. |
@@ -637,7 +638,6 @@ xfs_dir2_leafn_lookup_for_entry( | |||
637 | } | 638 | } |
638 | /* Didn't find an exact match. */ | 639 | /* Didn't find an exact match. */ |
639 | error = ENOENT; | 640 | error = ENOENT; |
640 | di = -1; | ||
641 | ASSERT(index == be16_to_cpu(leaf->hdr.count) || | 641 | ASSERT(index == be16_to_cpu(leaf->hdr.count) || |
642 | (args->op_flags & XFS_DA_OP_OKNOENT)); | 642 | (args->op_flags & XFS_DA_OP_OKNOENT)); |
643 | out: | 643 | out: |
@@ -652,7 +652,7 @@ out: | |||
652 | state->extravalid = 0; | 652 | state->extravalid = 0; |
653 | } | 653 | } |
654 | /* | 654 | /* |
655 | * Return the index, that will be the insertion point. | 655 | * Return the index, that will be the deletion point for remove/replace. |
656 | */ | 656 | */ |
657 | *indexp = index; | 657 | *indexp = index; |
658 | return XFS_ERROR(error); | 658 | return XFS_ERROR(error); |
@@ -1820,8 +1820,14 @@ xfs_dir2_node_lookup( | |||
1820 | error = xfs_da_node_lookup_int(state, &rval); | 1820 | error = xfs_da_node_lookup_int(state, &rval); |
1821 | if (error) | 1821 | if (error) |
1822 | rval = error; | 1822 | rval = error; |
1823 | else if (rval == ENOENT && args->cmpresult == XFS_CMP_CASE) | 1823 | else if (rval == ENOENT && args->cmpresult == XFS_CMP_CASE) { |
1824 | rval = EEXIST; /* a case-insensitive match was found */ | 1824 | /* If a CI match, dup the actual name and return EEXIST */ |
1825 | xfs_dir2_data_entry_t *dep; | ||
1826 | |||
1827 | dep = (xfs_dir2_data_entry_t *)((char *)state->extrablk.bp-> | ||
1828 | data + state->extrablk.index); | ||
1829 | rval = xfs_dir_cilookup_result(args, dep->name, dep->namelen); | ||
1830 | } | ||
1825 | /* | 1831 | /* |
1826 | * Release the btree blocks and leaf block. | 1832 | * Release the btree blocks and leaf block. |
1827 | */ | 1833 | */ |