From f0e2d93c29dc39ffd24cac180a19d48f700c0706 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Mon, 19 May 2008 16:31:57 +1000 Subject: [XFS] Remove unused arg from kmem_free() kmem_free() function takes (ptr, size) arguments but doesn't actually use second one. This patch removes size argument from all callsites. SGI-PV: 981498 SGI-Modid: xfs-linux-melb:xfs-kern:31050a Signed-off-by: Denys Vlasenko Signed-off-by: David Chinner Signed-off-by: Lachlan McIlroy --- fs/xfs/xfs_dir2_block.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'fs/xfs/xfs_dir2_block.c') diff --git a/fs/xfs/xfs_dir2_block.c b/fs/xfs/xfs_dir2_block.c index fb5a556725b3..e8a7aca5fe23 100644 --- a/fs/xfs/xfs_dir2_block.c +++ b/fs/xfs/xfs_dir2_block.c @@ -1071,7 +1071,7 @@ xfs_dir2_sf_to_block( */ error = xfs_dir2_grow_inode(args, XFS_DIR2_DATA_SPACE, &blkno); if (error) { - kmem_free(buf, buf_len); + kmem_free(buf); return error; } /* @@ -1079,7 +1079,7 @@ xfs_dir2_sf_to_block( */ error = xfs_dir2_data_init(args, blkno, &bp); if (error) { - kmem_free(buf, buf_len); + kmem_free(buf); return error; } block = bp->data; @@ -1198,7 +1198,7 @@ xfs_dir2_sf_to_block( sfep = xfs_dir2_sf_nextentry(sfp, sfep); } /* Done with the temporary buffer */ - kmem_free(buf, buf_len); + kmem_free(buf); /* * Sort the leaf entries by hash value. */ -- cgit From 5163f95a08cbf058ae16452c2242c5600fedc32e Mon Sep 17 00:00:00 2001 From: Barry Naujok Date: Wed, 21 May 2008 16:41:01 +1000 Subject: [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 Signed-off-by: Christoph Hellwig --- fs/xfs/xfs_dir2_block.c | 33 ++++++++++++++++++++++++--------- 1 file changed, 24 insertions(+), 9 deletions(-) (limited to 'fs/xfs/xfs_dir2_block.c') diff --git a/fs/xfs/xfs_dir2_block.c b/fs/xfs/xfs_dir2_block.c index e8a7aca5fe23..98588491cb0e 100644 --- a/fs/xfs/xfs_dir2_block.c +++ b/fs/xfs/xfs_dir2_block.c @@ -643,6 +643,7 @@ xfs_dir2_block_lookup_int( int mid; /* binary search current idx */ xfs_mount_t *mp; /* filesystem mount point */ xfs_trans_t *tp; /* transaction pointer */ + enum xfs_dacmp cmp; /* comparison result */ dp = args->dp; tp = args->trans; @@ -697,20 +698,31 @@ xfs_dir2_block_lookup_int( dep = (xfs_dir2_data_entry_t *) ((char *)block + xfs_dir2_dataptr_to_off(mp, addr)); /* - * Compare, if it's right give back buffer & entry number. + * Compare name and if it's an exact match, return the index + * and buffer. If it's the first case-insensitive match, store + * the index and buffer and continue looking for an exact match. */ - if (dep->namelen == args->namelen && - dep->name[0] == args->name[0] && - memcmp(dep->name, args->name, args->namelen) == 0) { + cmp = mp->m_dirnameops->compname(args, dep->name, dep->namelen); + if (cmp != XFS_CMP_DIFFERENT && cmp != args->cmpresult) { + args->cmpresult = cmp; *bpp = bp; *entno = mid; - return 0; + if (cmp == XFS_CMP_EXACT) + return 0; } - } while (++mid < be32_to_cpu(btp->count) && be32_to_cpu(blp[mid].hashval) == hash); + } while (++mid < be32_to_cpu(btp->count) && + be32_to_cpu(blp[mid].hashval) == hash); + + ASSERT(args->oknoent); + /* + * Here, we can only be doing a lookup (not a rename or replace). + * If a case-insensitive match was found earlier, return success. + */ + if (args->cmpresult == XFS_CMP_CASE) + return 0; /* * No match, release the buffer and return ENOENT. */ - ASSERT(args->oknoent); xfs_da_brelse(tp, bp); return XFS_ERROR(ENOENT); } @@ -1033,6 +1045,7 @@ xfs_dir2_sf_to_block( xfs_dir2_sf_t *sfp; /* shortform structure */ __be16 *tagp; /* end of data entry */ xfs_trans_t *tp; /* transaction pointer */ + struct xfs_name name; xfs_dir2_trace_args("sf_to_block", args); dp = args->dp; @@ -1187,8 +1200,10 @@ xfs_dir2_sf_to_block( tagp = xfs_dir2_data_entry_tag_p(dep); *tagp = cpu_to_be16((char *)dep - (char *)block); xfs_dir2_data_log_entry(tp, bp, dep); - blp[2 + i].hashval = cpu_to_be32(xfs_da_hashname( - (char *)sfep->name, sfep->namelen)); + name.name = sfep->name; + name.len = sfep->namelen; + blp[2 + i].hashval = cpu_to_be32(mp->m_dirnameops-> + hashname(&name)); blp[2 + i].address = cpu_to_be32(xfs_dir2_byte_to_dataptr(mp, (char *)dep - (char *)block)); offset = (int)((char *)(tagp + 1) - (char *)block); -- cgit From 6a178100abf01282eb697ab62b6086b2886dfc00 Mon Sep 17 00:00:00 2001 From: Barry Naujok Date: Wed, 21 May 2008 16:42:05 +1000 Subject: [XFS] Add op_flags field and helpers to xfs_da_args The end of the xfs_da_args structure has 4 unsigned char fields for true/false information on directory and attr operations using the xfs_da_args structure. The following converts these 4 into a op_flags field that uses the first 4 bits for these fields and allows expansion for future operation information (eg. case-insensitive lookup request). SGI-PV: 981520 SGI-Modid: xfs-linux-melb:xfs-kern:31206a Signed-off-by: Barry Naujok Signed-off-by: Christoph Hellwig --- fs/xfs/xfs_dir2_block.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) (limited to 'fs/xfs/xfs_dir2_block.c') diff --git a/fs/xfs/xfs_dir2_block.c b/fs/xfs/xfs_dir2_block.c index 98588491cb0e..dee225918db2 100644 --- a/fs/xfs/xfs_dir2_block.c +++ b/fs/xfs/xfs_dir2_block.c @@ -215,7 +215,7 @@ xfs_dir2_block_addname( /* * If this isn't a real add, we're done with the buffer. */ - if (args->justcheck) + if (args->op_flags & XFS_DA_OP_JUSTCHECK) xfs_da_brelse(tp, bp); /* * If we don't have space for the new entry & leaf ... @@ -225,7 +225,7 @@ xfs_dir2_block_addname( * Not trying to actually do anything, or don't have * a space reservation: return no-space. */ - if (args->justcheck || args->total == 0) + if ((args->op_flags & XFS_DA_OP_JUSTCHECK) || args->total == 0) return XFS_ERROR(ENOSPC); /* * Convert to the next larger format. @@ -240,7 +240,7 @@ xfs_dir2_block_addname( /* * Just checking, and it would work, so say so. */ - if (args->justcheck) + if (args->op_flags & XFS_DA_OP_JUSTCHECK) return 0; needlog = needscan = 0; /* @@ -674,7 +674,7 @@ xfs_dir2_block_lookup_int( else high = mid - 1; if (low > high) { - ASSERT(args->oknoent); + ASSERT(args->op_flags & XFS_DA_OP_OKNOENT); xfs_da_brelse(tp, bp); return XFS_ERROR(ENOENT); } @@ -713,7 +713,7 @@ xfs_dir2_block_lookup_int( } while (++mid < be32_to_cpu(btp->count) && be32_to_cpu(blp[mid].hashval) == hash); - ASSERT(args->oknoent); + ASSERT(args->op_flags & XFS_DA_OP_OKNOENT); /* * Here, we can only be doing a lookup (not a rename or replace). * If a case-insensitive match was found earlier, return success. -- cgit From 384f3ced07efdddf6838f6527366089d37843c94 Mon Sep 17 00:00:00 2001 From: Barry Naujok Date: Wed, 21 May 2008 16:58:22 +1000 Subject: [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 Signed-off-by: Christoph Hellwig --- fs/xfs/xfs_dir2_block.c | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) (limited to 'fs/xfs/xfs_dir2_block.c') diff --git a/fs/xfs/xfs_dir2_block.c b/fs/xfs/xfs_dir2_block.c index dee225918db2..e2fa0a1d8e96 100644 --- a/fs/xfs/xfs_dir2_block.c +++ b/fs/xfs/xfs_dir2_block.c @@ -610,14 +610,15 @@ xfs_dir2_block_lookup( /* * Get the offset from the leaf entry, to point to the data. */ - dep = (xfs_dir2_data_entry_t *) - ((char *)block + xfs_dir2_dataptr_to_off(mp, be32_to_cpu(blp[ent].address))); + dep = (xfs_dir2_data_entry_t *)((char *)block + + xfs_dir2_dataptr_to_off(mp, be32_to_cpu(blp[ent].address))); /* - * Fill in inode number, release the block. + * Fill in inode number, CI name if appropriate, release the block. */ args->inumber = be64_to_cpu(dep->inumber); + error = xfs_dir_cilookup_result(args, dep->name, dep->namelen); xfs_da_brelse(args->trans, bp); - return XFS_ERROR(EEXIST); + return XFS_ERROR(error); } /* -- cgit