aboutsummaryrefslogtreecommitdiffstats
path: root/fs/xfs/linux-2.6/xfs_iops.c
diff options
context:
space:
mode:
authorBarry Naujok <bnaujok@sgi.com>2008-05-21 02:58:22 -0400
committerNiv Sardi <xaiki@debian.org>2008-07-28 02:58:40 -0400
commit384f3ced07efdddf6838f6527366089d37843c94 (patch)
tree13037bc99115f6f940b6fe924b75dc48e0577678 /fs/xfs/linux-2.6/xfs_iops.c
parent9403540c0653122ca34884a180439ddbfcbcb524 (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.c57
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
396STATIC struct dentry *
397xfs_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
396STATIC int 432STATIC int
397xfs_vn_link( 433xfs_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
931const 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
895const struct inode_operations xfs_symlink_inode_operations = { 950const 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,