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/linux-2.6/xfs_iops.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/linux-2.6/xfs_iops.c')
-rw-r--r-- | fs/xfs/linux-2.6/xfs_iops.c | 57 |
1 files changed, 56 insertions, 1 deletions
diff --git a/fs/xfs/linux-2.6/xfs_iops.c b/fs/xfs/linux-2.6/xfs_iops.c index 13b6cfd366c2..9f0f8ee8d44d 100644 --- a/fs/xfs/linux-2.6/xfs_iops.c +++ b/fs/xfs/linux-2.6/xfs_iops.c | |||
@@ -382,7 +382,7 @@ xfs_vn_lookup( | |||
382 | return ERR_PTR(-ENAMETOOLONG); | 382 | return ERR_PTR(-ENAMETOOLONG); |
383 | 383 | ||
384 | xfs_dentry_to_name(&name, dentry); | 384 | xfs_dentry_to_name(&name, dentry); |
385 | error = xfs_lookup(XFS_I(dir), &name, &cip); | 385 | error = xfs_lookup(XFS_I(dir), &name, &cip, NULL); |
386 | if (unlikely(error)) { | 386 | if (unlikely(error)) { |
387 | if (unlikely(error != ENOENT)) | 387 | if (unlikely(error != ENOENT)) |
388 | return ERR_PTR(-error); | 388 | return ERR_PTR(-error); |
@@ -393,6 +393,42 @@ xfs_vn_lookup( | |||
393 | return d_splice_alias(cip->i_vnode, dentry); | 393 | return d_splice_alias(cip->i_vnode, dentry); |
394 | } | 394 | } |
395 | 395 | ||
396 | STATIC struct dentry * | ||
397 | xfs_vn_ci_lookup( | ||
398 | struct inode *dir, | ||
399 | struct dentry *dentry, | ||
400 | struct nameidata *nd) | ||
401 | { | ||
402 | struct xfs_inode *ip; | ||
403 | struct xfs_name xname; | ||
404 | struct xfs_name ci_name; | ||
405 | struct qstr dname; | ||
406 | int error; | ||
407 | |||
408 | if (dentry->d_name.len >= MAXNAMELEN) | ||
409 | return ERR_PTR(-ENAMETOOLONG); | ||
410 | |||
411 | xfs_dentry_to_name(&xname, dentry); | ||
412 | error = xfs_lookup(XFS_I(dir), &xname, &ip, &ci_name); | ||
413 | if (unlikely(error)) { | ||
414 | if (unlikely(error != ENOENT)) | ||
415 | return ERR_PTR(-error); | ||
416 | d_add(dentry, NULL); | ||
417 | return NULL; | ||
418 | } | ||
419 | |||
420 | /* if exact match, just splice and exit */ | ||
421 | if (!ci_name.name) | ||
422 | return d_splice_alias(ip->i_vnode, dentry); | ||
423 | |||
424 | /* else case-insensitive match... */ | ||
425 | dname.name = ci_name.name; | ||
426 | dname.len = ci_name.len; | ||
427 | dentry = d_add_ci(ip->i_vnode, dentry, &dname); | ||
428 | kmem_free(ci_name.name); | ||
429 | return dentry; | ||
430 | } | ||
431 | |||
396 | STATIC int | 432 | STATIC int |
397 | xfs_vn_link( | 433 | xfs_vn_link( |
398 | struct dentry *old_dentry, | 434 | struct dentry *old_dentry, |
@@ -892,6 +928,25 @@ const struct inode_operations xfs_dir_inode_operations = { | |||
892 | .removexattr = xfs_vn_removexattr, | 928 | .removexattr = xfs_vn_removexattr, |
893 | }; | 929 | }; |
894 | 930 | ||
931 | const struct inode_operations xfs_dir_ci_inode_operations = { | ||
932 | .create = xfs_vn_create, | ||
933 | .lookup = xfs_vn_ci_lookup, | ||
934 | .link = xfs_vn_link, | ||
935 | .unlink = xfs_vn_unlink, | ||
936 | .symlink = xfs_vn_symlink, | ||
937 | .mkdir = xfs_vn_mkdir, | ||
938 | .rmdir = xfs_vn_rmdir, | ||
939 | .mknod = xfs_vn_mknod, | ||
940 | .rename = xfs_vn_rename, | ||
941 | .permission = xfs_vn_permission, | ||
942 | .getattr = xfs_vn_getattr, | ||
943 | .setattr = xfs_vn_setattr, | ||
944 | .setxattr = xfs_vn_setxattr, | ||
945 | .getxattr = xfs_vn_getxattr, | ||
946 | .listxattr = xfs_vn_listxattr, | ||
947 | .removexattr = xfs_vn_removexattr, | ||
948 | }; | ||
949 | |||
895 | const struct inode_operations xfs_symlink_inode_operations = { | 950 | const struct inode_operations xfs_symlink_inode_operations = { |
896 | .readlink = generic_readlink, | 951 | .readlink = generic_readlink, |
897 | .follow_link = xfs_vn_follow_link, | 952 | .follow_link = xfs_vn_follow_link, |