From: David Chinner <dgc@sgi.com>
To: Barry Naujok <bnaujok@sgi.com>
Cc: xfs@oss.sgi.com, linux-fsdevel@vger.kernel.org
Subject: Re: [PATCH 4/7] XFS: Return case-insensitive match for dentry cache
Date: Thu, 3 Apr 2008 15:22:09 +1000 [thread overview]
Message-ID: <20080403052209.GR103491721@sgi.com> (raw)
In-Reply-To: <20080402062708.654277049@chook.melbourne.sgi.com>
On Wed, Apr 02, 2008 at 04:25:12PM +1000, Barry Naujok wrote:
> 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.
>
> It also introduces a new type, xfs_name, which is similar to the
> dentry cache's qstr type. It contains a pointer to a zone allocated
> string (MAXNAMELEN sized) and the length of the actual name. This
> string does not need to be NULL terminated (a counted string).
>
> xfs_name_t is only used in the lookup path for this patch, but may
> be used in other locations too if desired. It maybe desirable not
> to use xfs_name_t at all in the lookup functions but stick to
> separate parameters (which will mean 7 instead of 5 arguments).
>
> To avoid polluting the dcache, we implement a new directory inode
> operations for lookup. xfs_vn_ci_lookup() interacts directly with
> the dcache and the code was derived from ntfs_lookup() in
> fs/ntfs/namei.c. The dentry hash and compare overrides introduced
> in the ASCII-CI patch has been removed.
>
> The "actual name" is only allocated and returned for a case-
> insensitive match and not an actual match.
> +STATIC struct dentry *
> +xfs_vn_ci_lookup(
> + struct inode *dir,
> + struct dentry *dentry,
> + struct nameidata *nd)
> +{
> + struct xfs_inode *cip;
> + int error;
> struct dentry *result;
> + struct qstr ci_name = {0, 0, NULL};
> + struct inode *inode;
>
> if (dentry->d_name.len >= MAXNAMELEN)
> return ERR_PTR(-ENAMETOOLONG);
>
> - if (xfs_sb_version_hasoldci(&mp->m_sb))
> - dentry->d_op = &xfs_ci_dentry_operations;
> + error = xfs_lookup(XFS_I(dir), &dentry->d_name, &cip, &ci_name);
Bit confusing with cip = "child inode" and ci_name = "case insensitive".
i.e. same prefix, different meanings...
>
> - error = xfs_lookup(XFS_I(dir), dentry, &cip);
> if (unlikely(error)) {
> if (unlikely(error != ENOENT))
> return ERR_PTR(-error);
> d_add(dentry, NULL);
> return NULL;
> }
> + inode = cip->i_vnode;
> +
> + /* if exact match, just splice and exit */
> + if (!ci_name.name) {
> + result = d_splice_alias(inode, dentry);
> + return result;
> + }
if (!ci_name.name)
return d_splice_alias(inode, dentry);
>
> - result = d_splice_alias(cip->i_vnode, dentry);
> - if (result)
> - result->d_op = dentry->d_op;
> - return result;
> + /*
> + * case-insensitive match, create a dentry to return and fill it
> + * in with the correctly cased name. Parameter "dentry" is not
> + * used anymore and the caller will free it.
> + * Derived from fs/ntfs/namei.c
> + */
> +
> + ci_name.hash = full_name_hash(ci_name.name, ci_name.len);
> +
> + /* Does an existing dentry match? */
> + result = d_lookup(dentry->d_parent, &ci_name);
> + if (!result) {
> + /* if not, create one */
> + result = d_alloc(dentry->d_parent, &ci_name);
> + xfs_da_name_free((char *)ci_name.name);
> + if (!result)
> + return ERR_PTR(-ENOMEM);
> + dentry = d_splice_alias(inode, result);
> + if (dentry) {
> + dput(result);
> + return dentry;
> + }
> + return result;
> + }
This looks like it came from the ntfs code - i find that much easier
to follow with "real_dent" and "new_dent" instead of "result" and "dentry"
respectively.
> + xfs_da_name_free((char *)ci_name.name);
> +
> + /* an existing dentry matches, use it */
Ah, I see the rest of this is basically a copy and paste of the ntfs code
(without some of the useful comments). I think a generic helper function
is in order here that contains all the coments from the ntfs code....
> +
> + if (result->d_inode) {
> + /*
> + * already an inode attached, deref the inode that was
> + * refcounted with xfs_lookup and return the dentry.
> + */
> + if (unlikely(result->d_inode != inode)) {
> + /* This can happen because bad inodes are unhashed. */
> + BUG_ON(!is_bad_inode(inode));
> + BUG_ON(!is_bad_inode(result->d_inode));
Bit drastic - how about failing the lookup and returning EIO in this case?
> + }
> + iput(inode);
> + return result;
> + }
.....
> Index: kern_ci/fs/xfs/linux-2.6/xfs_super.c
> ===================================================================
> --- kern_ci.orig/fs/xfs/linux-2.6/xfs_super.c
> +++ kern_ci/fs/xfs/linux-2.6/xfs_super.c
> @@ -566,7 +566,10 @@ xfs_set_inodeops(
> inode->i_mapping->a_ops = &xfs_address_space_operations;
> break;
> case S_IFDIR:
> - inode->i_op = &xfs_dir_inode_operations;
> + inode->i_op =
> + xfs_sb_version_hasoldci(&XFS_I(inode)->i_mount->m_sb) ?
+ xfs_sb_version_hasoldci(&XFS_M(inode->i_sb)->m_sb) ?
> + xfs_ino_t *inum, /* out: inode number */
> + xfs_name_t *ci_name) /* out: actual name if different */
> {
> xfs_da_args_t args;
> int rval;
> @@ -259,9 +260,9 @@ xfs_dir_lookup(
> ASSERT((dp->i_d.di_mode & S_IFMT) == S_IFDIR);
> XFS_STATS_INC(xs_dir_lookup);
>
> - args.name = name;
> - args.namelen = namelen;
> - args.hashval = xfs_dir_hashname(dp, name, namelen);
> + args.name = name->name;
> + args.namelen = name->len;
> + args.hashval = xfs_dir_hashname(dp, name->name, name->len);
> args.inumber = 0;
> args.dp = dp;
> args.firstblock = NULL;
> @@ -272,6 +273,8 @@ xfs_dir_lookup(
> args.justcheck = args.addname = 0;
> args.oknoent = 1;
> args.cmpresult = XFS_CMP_DIFFERENT;
> + args.value = NULL;
> + args.valuelen = 0;
Rather than initialising more of the args to zero (already 7 members
explicitly initialised to zero or NULL), change it to:
memset(&args, 0, sizeof(xfs_da_args_t));
args.name = name->name;
args.namelen = name->len;
args.hashval = xfs_dir_hashname(dp, name->name, name->len);
args.dp = dp;
args.whichfork = XFS_DATA_FORK;
args.trans = tp;
args.oknoent = 1;
args.cmpresult = XFS_CMP_DIFFERENT;
>
> if (dp->i_d.di_format == XFS_DINODE_FMT_LOCAL)
> rval = xfs_dir2_sf_lookup(&args);
> @@ -287,8 +290,17 @@ xfs_dir_lookup(
> rval = xfs_dir2_node_lookup(&args);
> if (rval == EEXIST)
> rval = 0;
> - if (rval == 0)
> + if (rval == 0) {
if (!rval) {
> Index: kern_ci/fs/xfs/xfs_dir2_block.c
> ===================================================================
> --- kern_ci.orig/fs/xfs/xfs_dir2_block.c
> +++ kern_ci/fs/xfs/xfs_dir2_block.c
> @@ -616,6 +616,15 @@ xfs_dir2_block_lookup(
> * Fill in inode number, release the block.
> */
> args->inumber = be64_to_cpu(dep->inumber);
> + /*
> + * If a case-insensitive match, allocate a buffer and copy the actual
> + * name into the buffer. Return it via args->value.
> + */
> + if (args->cmpresult == XFS_CMP_CASE) {
> + args->value = xfs_da_name_alloc();
> + memcpy(args->value, dep->name, dep->namelen);
> + args->valuelen = dep->namelen;
xfs_da_ci_name_dup();
> + }
> xfs_da_brelse(args->trans, bp);
> return XFS_ERROR(EEXIST);
> }
> Index: kern_ci/fs/xfs/xfs_dir2_leaf.c
> ===================================================================
> --- kern_ci.orig/fs/xfs/xfs_dir2_leaf.c
> +++ kern_ci/fs/xfs/xfs_dir2_leaf.c
> @@ -1301,6 +1301,15 @@ xfs_dir2_leaf_lookup(
> * Return the found inode number.
> */
> args->inumber = be64_to_cpu(dep->inumber);
> + /*
> + * If a case-insensitive match, allocate a buffer and copy the actual
> + * name into the buffer. Return it via args->value.
> + */
> + if (args->cmpresult == XFS_CMP_CASE) {
> + args->value = xfs_da_name_alloc();
> + memcpy(args->value, dep->name, dep->namelen);
> + args->valuelen = dep->namelen;
xfs_da_ci_name_dup();
> + }
> xfs_da_brelse(tp, dbp);
> xfs_da_brelse(tp, lbp);
> return XFS_ERROR(EEXIST);
> Index: kern_ci/fs/xfs/xfs_dir2_node.c
> ===================================================================
> --- kern_ci.orig/fs/xfs/xfs_dir2_node.c
> +++ kern_ci/fs/xfs/xfs_dir2_node.c
> @@ -643,6 +643,8 @@ xfs_dir2_leafn_lookup_for_entry(
> xfs_dir2_dataptr_to_off(mp, be32_to_cpu(lep->address)));
> /*
> * Compare the entry, return it if it matches.
> + * "oknoent" is set for lookup and clear for
> + * remove and replace.
> */
That should have been in an earlier patch....
> cmp = args->oknoent ?
> xfs_dir_compname(dp, dep->name, dep->namelen,
> @@ -1857,10 +1859,22 @@ xfs_dir2_node_lookup(
> if (error)
> rval = error;
> /*
> - * If case-insensitive match was found in a leaf, return EEXIST.
> - */
> - else if (rval == ENOENT && args->cmpresult == XFS_CMP_CASE)
> + * If case-insensitive match was found (xfs_dir2_leafn_lookup_int
> + * returns ENOENT for a case-insensitive match, but sets
> + * args->cmpresult to XFS_CMP_CASE):
> + * - Allocate a buffer and copy the actual name into the buffer and
> + * return it via args->value.
> + * - set rval to EEXIST
> + */
> + else if (rval == ENOENT && args->cmpresult == XFS_CMP_CASE) {
> + xfs_dir2_data_entry_t *dep = (xfs_dir2_data_entry_t *)
> + ((char *)state->extrablk.bp->data +
> + state->extrablk.index);
> + args->value = xfs_da_name_alloc();
> + memcpy(args->value, dep->name, dep->namelen);
> + args->valuelen = dep->namelen;
> rval = EEXIST;
> + }
Yeah, more reason to move the comment inside the if block....
oh, and xfs_da_ci_name_dup()....
> - if (args->cmpresult == XFS_CMP_CASE)
> + if (args->cmpresult == XFS_CMP_CASE) {
> + /*
> + * If a case-insensitive match, allocate a buffer and copy the
> + * actual name into the buffer and return it via args->value.
> + */
> + args->value = xfs_da_name_alloc();
> + memcpy(args->value, ci_sfep->name, ci_sfep->namelen);
> + args->valuelen = ci_sfep->namelen;
xfs_da_ci_name_dup()
> --- kern_ci.orig/fs/xfs/xfs_utils.c
> +++ kern_ci/fs/xfs/xfs_utils.c
> @@ -24,6 +24,7 @@
> #include "xfs_trans.h"
> #include "xfs_sb.h"
> #include "xfs_ag.h"
> +#include "xfs_da_btree.h"
What's that needed for? What ever it is, i think you've put it
in the wrong header file....
Cheers,
Dave.
--
Dave Chinner
Principal Engineer
SGI Australian Software Group
next prev parent reply other threads:[~2008-04-03 5:22 UTC|newest]
Thread overview: 48+ messages / expand[flat|nested] mbox.gz Atom feed top
2008-04-02 6:25 [PATCH 0/7] XFS: case-insensitive lookup and Unicode support Barry Naujok
2008-04-02 6:25 ` [PATCH 1/7] XFS: Name operation vector for hash and compare Barry Naujok
2008-04-03 0:22 ` Josef 'Jeff' Sipek
2008-04-03 4:50 ` Barry Naujok
2008-04-03 1:29 ` David Chinner
2008-04-03 1:45 ` Barry Naujok
2008-04-03 22:51 ` Christoph Hellwig
2008-04-02 6:25 ` [PATCH 2/7] XFS: ASCII case-insensitive support Barry Naujok
2008-04-03 0:35 ` Josef 'Jeff' Sipek
2008-04-03 1:53 ` David Chinner
2008-04-03 17:09 ` Christoph Hellwig
2008-04-03 22:55 ` Christoph Hellwig
2008-04-02 6:25 ` [PATCH 3/7] XFS: Refactor node format directory lookup/addname Barry Naujok
2008-04-03 1:51 ` Josef 'Jeff' Sipek
2008-04-03 4:04 ` Barry Naujok
2008-04-03 4:10 ` Barry Naujok
2008-04-03 4:33 ` David Chinner
2008-04-02 6:25 ` [PATCH 4/7] XFS: Return case-insensitive match for dentry cache Barry Naujok
2008-04-03 2:34 ` Josef 'Jeff' Sipek
2008-04-03 5:22 ` David Chinner [this message]
2008-04-03 5:41 ` Stephen Rothwell
2008-04-03 14:56 ` Christoph Hellwig
2008-04-03 23:06 ` Christoph Hellwig
2008-04-02 6:25 ` [PATCH 5/7] XFS: Unicode case-insensitive lookup implementation Barry Naujok
2008-04-03 8:31 ` David Chinner
2008-04-17 5:38 ` Barry Naujok
2008-04-17 8:49 ` David Chinner
2008-04-03 17:14 ` Christoph Hellwig
2008-04-03 17:24 ` Jeremy Allison
2008-04-03 18:09 ` Josef 'Jeff' Sipek
2008-04-03 18:11 ` Eric Sandeen
2008-04-03 18:22 ` Jeremy Allison
2008-04-04 0:00 ` Mark Goodwin
2008-04-03 18:43 ` Christoph Hellwig
2008-04-03 18:47 ` Jeremy Allison
2008-04-03 18:55 ` Christoph Hellwig
2008-04-03 18:57 ` Christoph Hellwig
2008-04-03 22:34 ` Jeremy Allison
2008-04-03 22:20 ` David Chinner
2008-04-03 22:31 ` Christoph Hellwig
2008-04-03 23:00 ` Jamie Lokier
2008-04-02 6:25 ` [PATCH 6/7] XFS: Native Language Support for Unicode in XFS Barry Naujok
2008-04-04 0:05 ` David Chinner
2008-04-02 6:25 ` [PATCH 7/7] XFS: NLS config option Barry Naujok
2008-04-03 1:26 ` Josef 'Jeff' Sipek
2008-04-03 1:38 ` Barry Naujok
2008-04-08 11:45 ` [PATCH 0/7] XFS: case-insensitive lookup and Unicode support Christoph Hellwig
2008-04-09 1:53 ` Barry Naujok
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20080403052209.GR103491721@sgi.com \
--to=dgc@sgi.com \
--cc=bnaujok@sgi.com \
--cc=linux-fsdevel@vger.kernel.org \
--cc=xfs@oss.sgi.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).