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.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.c')
-rw-r--r-- | fs/xfs/xfs_dir2.c | 40 |
1 files changed, 38 insertions, 2 deletions
diff --git a/fs/xfs/xfs_dir2.c b/fs/xfs/xfs_dir2.c index 3387acd3e471..882609c699c8 100644 --- a/fs/xfs/xfs_dir2.c +++ b/fs/xfs/xfs_dir2.c | |||
@@ -193,14 +193,43 @@ xfs_dir_createname( | |||
193 | } | 193 | } |
194 | 194 | ||
195 | /* | 195 | /* |
196 | * If doing a CI lookup and case-insensitive match, dup actual name into | ||
197 | * args.value. Return EEXIST for success (ie. name found) or an error. | ||
198 | */ | ||
199 | int | ||
200 | xfs_dir_cilookup_result( | ||
201 | struct xfs_da_args *args, | ||
202 | const char *name, | ||
203 | int len) | ||
204 | { | ||
205 | if (args->cmpresult == XFS_CMP_DIFFERENT) | ||
206 | return ENOENT; | ||
207 | if (args->cmpresult != XFS_CMP_CASE || | ||
208 | !(args->op_flags & XFS_DA_OP_CILOOKUP)) | ||
209 | return EEXIST; | ||
210 | |||
211 | args->value = kmem_alloc(len, KM_MAYFAIL); | ||
212 | if (!args->value) | ||
213 | return ENOMEM; | ||
214 | |||
215 | memcpy(args->value, name, len); | ||
216 | args->valuelen = len; | ||
217 | return EEXIST; | ||
218 | } | ||
219 | |||
220 | /* | ||
196 | * Lookup a name in a directory, give back the inode number. | 221 | * Lookup a name in a directory, give back the inode number. |
222 | * If ci_name is not NULL, returns the actual name in ci_name if it differs | ||
223 | * to name, or ci_name->name is set to NULL for an exact match. | ||
197 | */ | 224 | */ |
225 | |||
198 | int | 226 | int |
199 | xfs_dir_lookup( | 227 | xfs_dir_lookup( |
200 | xfs_trans_t *tp, | 228 | xfs_trans_t *tp, |
201 | xfs_inode_t *dp, | 229 | xfs_inode_t *dp, |
202 | struct xfs_name *name, | 230 | struct xfs_name *name, |
203 | xfs_ino_t *inum) /* out: inode number */ | 231 | xfs_ino_t *inum, /* out: inode number */ |
232 | struct xfs_name *ci_name) /* out: actual name if CI match */ | ||
204 | { | 233 | { |
205 | xfs_da_args_t args; | 234 | xfs_da_args_t args; |
206 | int rval; | 235 | int rval; |
@@ -217,6 +246,8 @@ xfs_dir_lookup( | |||
217 | args.whichfork = XFS_DATA_FORK; | 246 | args.whichfork = XFS_DATA_FORK; |
218 | args.trans = tp; | 247 | args.trans = tp; |
219 | args.op_flags = XFS_DA_OP_OKNOENT; | 248 | args.op_flags = XFS_DA_OP_OKNOENT; |
249 | if (ci_name) | ||
250 | args.op_flags |= XFS_DA_OP_CILOOKUP; | ||
220 | args.cmpresult = XFS_CMP_DIFFERENT; | 251 | args.cmpresult = XFS_CMP_DIFFERENT; |
221 | 252 | ||
222 | if (dp->i_d.di_format == XFS_DINODE_FMT_LOCAL) | 253 | if (dp->i_d.di_format == XFS_DINODE_FMT_LOCAL) |
@@ -233,8 +264,13 @@ xfs_dir_lookup( | |||
233 | rval = xfs_dir2_node_lookup(&args); | 264 | rval = xfs_dir2_node_lookup(&args); |
234 | if (rval == EEXIST) | 265 | if (rval == EEXIST) |
235 | rval = 0; | 266 | rval = 0; |
236 | if (rval == 0) | 267 | if (!rval) { |
237 | *inum = args.inumber; | 268 | *inum = args.inumber; |
269 | if (ci_name) { | ||
270 | ci_name->name = args.value; | ||
271 | ci_name->len = args.valuelen; | ||
272 | } | ||
273 | } | ||
238 | return rval; | 274 | return rval; |
239 | } | 275 | } |
240 | 276 | ||