diff options
author | Barry Naujok <bnaujok@sgi.com> | 2008-05-21 02:41:01 -0400 |
---|---|---|
committer | Niv Sardi <xaiki@debian.org> | 2008-07-28 02:58:36 -0400 |
commit | 5163f95a08cbf058ae16452c2242c5600fedc32e (patch) | |
tree | 5d6b905f7031144a62fb1fa17ba3106d99268003 /fs/xfs/xfs_dir2_node.c | |
parent | 68f34d5107dbace3d14a1c2f060fc8941894879c (diff) |
[XFS] Name operation vector for hash and compare
Adds two pieces of functionality for the basis of case-insensitive support
in XFS:
1. A comparison result enumerated type: xfs_dacmp. It represents an
exact match, case-insensitive match or no match at all. This patch
only implements different and exact results.
2. xfs_nameops vector for specifying how to perform the hash generation
of filenames and comparision methods. In this patch the hash vector
points to the existing xfs_da_hashname function and the comparison
method does a length compare, and if the same, does a memcmp and
return the xfs_dacmp result.
All filename functions that use the hash (create, lookup remove, rename,
etc) now use the xfs_nameops.hashname function and all directory lookup
functions also use the xfs_nameops.compname function.
The lookup functions also handle case-insensitive results even though the
default comparison function cannot return that. And important aspect of
the lookup functions is that an exact match always has precedence over a
case-insensitive. So while a case-insensitive match is found, we have to
keep looking just in case there is an exact match. In the meantime, the
info for the first case-insensitive match is retained if no exact match is
found.
SGI-PV: 981519
SGI-Modid: xfs-linux-melb:xfs-kern:31205a
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 | 23 |
1 files changed, 14 insertions, 9 deletions
diff --git a/fs/xfs/xfs_dir2_node.c b/fs/xfs/xfs_dir2_node.c index e29b7c63e198..fedf8f976a10 100644 --- a/fs/xfs/xfs_dir2_node.c +++ b/fs/xfs/xfs_dir2_node.c | |||
@@ -556,6 +556,7 @@ xfs_dir2_leafn_lookup_for_entry( | |||
556 | xfs_mount_t *mp; /* filesystem mount point */ | 556 | xfs_mount_t *mp; /* filesystem mount point */ |
557 | xfs_dir2_db_t newdb; /* new data block number */ | 557 | xfs_dir2_db_t newdb; /* new data block number */ |
558 | xfs_trans_t *tp; /* transaction pointer */ | 558 | xfs_trans_t *tp; /* transaction pointer */ |
559 | enum xfs_dacmp cmp; /* comparison result */ | ||
559 | 560 | ||
560 | dp = args->dp; | 561 | dp = args->dp; |
561 | tp = args->trans; | 562 | tp = args->trans; |
@@ -620,17 +621,21 @@ xfs_dir2_leafn_lookup_for_entry( | |||
620 | dep = (xfs_dir2_data_entry_t *)((char *)curbp->data + | 621 | dep = (xfs_dir2_data_entry_t *)((char *)curbp->data + |
621 | xfs_dir2_dataptr_to_off(mp, be32_to_cpu(lep->address))); | 622 | xfs_dir2_dataptr_to_off(mp, be32_to_cpu(lep->address))); |
622 | /* | 623 | /* |
623 | * Compare the entry, return it if it matches. | 624 | * Compare the entry and if it's an exact match, return |
625 | * EEXIST immediately. If it's the first case-insensitive | ||
626 | * match, store the inode number and continue looking. | ||
624 | */ | 627 | */ |
625 | if (dep->namelen == args->namelen && memcmp(dep->name, | 628 | cmp = mp->m_dirnameops->compname(args, dep->name, dep->namelen); |
626 | args->name, args->namelen) == 0) { | 629 | if (cmp != XFS_CMP_DIFFERENT && cmp != args->cmpresult) { |
630 | args->cmpresult = cmp; | ||
627 | args->inumber = be64_to_cpu(dep->inumber); | 631 | args->inumber = be64_to_cpu(dep->inumber); |
628 | di = (int)((char *)dep - (char *)curbp->data); | 632 | di = (int)((char *)dep - (char *)curbp->data); |
629 | error = EEXIST; | 633 | error = EEXIST; |
630 | goto out; | 634 | if (cmp == XFS_CMP_EXACT) |
635 | goto out; | ||
631 | } | 636 | } |
632 | } | 637 | } |
633 | /* Didn't find a match. */ | 638 | /* Didn't find an exact match. */ |
634 | error = ENOENT; | 639 | error = ENOENT; |
635 | di = -1; | 640 | di = -1; |
636 | ASSERT(index == be16_to_cpu(leaf->hdr.count) || args->oknoent); | 641 | ASSERT(index == be16_to_cpu(leaf->hdr.count) || args->oknoent); |
@@ -1813,6 +1818,8 @@ xfs_dir2_node_lookup( | |||
1813 | error = xfs_da_node_lookup_int(state, &rval); | 1818 | error = xfs_da_node_lookup_int(state, &rval); |
1814 | if (error) | 1819 | if (error) |
1815 | rval = error; | 1820 | rval = error; |
1821 | else if (rval == ENOENT && args->cmpresult == XFS_CMP_CASE) | ||
1822 | rval = EEXIST; /* a case-insensitive match was found */ | ||
1816 | /* | 1823 | /* |
1817 | * Release the btree blocks and leaf block. | 1824 | * Release the btree blocks and leaf block. |
1818 | */ | 1825 | */ |
@@ -1856,9 +1863,8 @@ xfs_dir2_node_removename( | |||
1856 | * Look up the entry we're deleting, set up the cursor. | 1863 | * Look up the entry we're deleting, set up the cursor. |
1857 | */ | 1864 | */ |
1858 | error = xfs_da_node_lookup_int(state, &rval); | 1865 | error = xfs_da_node_lookup_int(state, &rval); |
1859 | if (error) { | 1866 | if (error) |
1860 | rval = error; | 1867 | rval = error; |
1861 | } | ||
1862 | /* | 1868 | /* |
1863 | * Didn't find it, upper layer screwed up. | 1869 | * Didn't find it, upper layer screwed up. |
1864 | */ | 1870 | */ |
@@ -1875,9 +1881,8 @@ xfs_dir2_node_removename( | |||
1875 | */ | 1881 | */ |
1876 | error = xfs_dir2_leafn_remove(args, blk->bp, blk->index, | 1882 | error = xfs_dir2_leafn_remove(args, blk->bp, blk->index, |
1877 | &state->extrablk, &rval); | 1883 | &state->extrablk, &rval); |
1878 | if (error) { | 1884 | if (error) |
1879 | return error; | 1885 | return error; |
1880 | } | ||
1881 | /* | 1886 | /* |
1882 | * Fix the hash values up the btree. | 1887 | * Fix the hash values up the btree. |
1883 | */ | 1888 | */ |