linux-fsdevel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* path_lookup() alternative
@ 2012-01-23 10:19 dmitry.krivenok
  2012-01-23 21:23 ` Al Viro
  0 siblings, 1 reply; 4+ messages in thread
From: dmitry.krivenok @ 2012-01-23 10:19 UTC (permalink / raw)
  To: linux-fsdevel

Hello,
I sent this question to Al Viro first, but didn't get any feedback, so reposting here and hope that someone can help me.

I'm trying to build existing system consisting of several kernel modules and user-space tools on the latest vanilla kernel.
Previously, we used path_lookup() function to perform lookup with arbitrary flags (e.g. we passed LOOKUP_PARENT in
some cases) and save results in nameidata structure. Then, this structure was passed to other kernel functions (e.g. 
lookup_hash and then lookup_one_len) or was used directly in the module code.

The problem is that path_lookup() was removed in c9c6cac0c2bdbda42e7b804838648d0bc60ddb13 and kern_path_parent
was added instead (and, of course, it didn't allow user to pass arbitrary flags).
Then, in e3c3d9c838d48c0341c40ea45ee087e3d8c8ea39, kern_path_parent() was unexported and thus became unavailable for us.

I spent several hours learning path lookup code in the kernel tree, but didn't find a function/method which allows to get properly filled 
nameidata having only path and flags.
Is there an alternative to removed path_lookup() function or any other way of {path, flags}->{nameidata} translation?

Thanks in advance,
Dmitry

^ permalink raw reply	[flat|nested] 4+ messages in thread

* Re: path_lookup() alternative
  2012-01-23 10:19 path_lookup() alternative dmitry.krivenok
@ 2012-01-23 21:23 ` Al Viro
  2012-01-24 13:03   ` dmitry.krivenok
  0 siblings, 1 reply; 4+ messages in thread
From: Al Viro @ 2012-01-23 21:23 UTC (permalink / raw)
  To: dmitry.krivenok; +Cc: linux-fsdevel

On Mon, Jan 23, 2012 at 05:19:24AM -0500, dmitry.krivenok@emc.com wrote:
> Hello,
> I sent this question to Al Viro first, but didn't get any feedback, so reposting here and hope that someone can help me.
> 
> I'm trying to build existing system consisting of several kernel modules and user-space tools on the latest vanilla kernel.
> Previously, we used path_lookup() function to perform lookup with arbitrary flags (e.g. we passed LOOKUP_PARENT in
> some cases) and save results in nameidata structure. Then, this structure was passed to other kernel functions (e.g. 
> lookup_hash and then lookup_one_len) or was used directly in the module code.

lookup_one_len() does not take nameidata at all.
lookup_hash() is not only not exported, it's _static_.

what are you talking about?

> The problem is that path_lookup() was removed in c9c6cac0c2bdbda42e7b804838648d0bc60ddb13 and kern_path_parent
> was added instead (and, of course, it didn't allow user to pass arbitrary flags).
> Then, in e3c3d9c838d48c0341c40ea45ee087e3d8c8ea39, kern_path_parent() was unexported and thus became unavailable for us.
> 
> I spent several hours learning path lookup code in the kernel tree, but didn't find a function/method which allows to get properly filled 
> nameidata having only path and flags.
> Is there an alternative to removed path_lookup() function or any other way of {path, flags}->{nameidata} translation?

Depends on what do you want to do with it.  IMO nameidata should be internal to
fs/namei.c; we still have it exposed more than I'd like it to be and if nothing
else, that exposure is going to shrink.

Details of your use case, please (ideally - along with the reference to your
code).

^ permalink raw reply	[flat|nested] 4+ messages in thread

* RE: path_lookup() alternative
  2012-01-23 21:23 ` Al Viro
@ 2012-01-24 13:03   ` dmitry.krivenok
  2012-01-24 17:19     ` Andreas Dilger
  0 siblings, 1 reply; 4+ messages in thread
From: dmitry.krivenok @ 2012-01-24 13:03 UTC (permalink / raw)
  To: viro; +Cc: linux-fsdevel

Hi Al, thanks for quick reply.

The module I'm working on is intended to work on wide range of kernels, so
we have lots of #ifdefs. For example, out internal hash lookup routine looks like:

static struct dentry * int_lookup_hash(struct nameidata *nd)
{
#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,15))
    return lookup_hash(&nd->last, NDP_TO_DENTRY(nd));
#elif (LINUX_VERSION_CODE  >= KERNEL_VERSION(2,6,16))
    return lookup_one_len(nd->last.name, NDP_TO_DENTRY(nd), nd->last.len);
#else
    return lookup_hash(nd);
#endif
}

Where NDP_TO_DENTRY is defined as follows:

#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,25))
#define NDP_TO_DENTRY(_ndp) (_ndp)->path.dentry
#else
#define NDP_TO_DENTRY(_ndp) (_ndp)->dentry
#endif

As you can see, lookup_hash() wasn't static is previous kernel versions.

Yes, lookup_one_len() doesn't take whole nameidata, but it may be called 
as follows (code from drivers/base/devtmpfs.c):

kern_path_parent(name, &nd);
...
dentry = lookup_one_len(nd.last.name, nd.path.dentry, nd.last.len);

That's how we call lookup_one_len() in our module and we need a way to fill 
nameidata structure and then pass some of its fields to this function.
path_lookup() was responsible for filling nameidata so it could then be passed
to other kernel functions, but path_lookup() was removed.

Our module has functions which implement file/directory operations in kernel-space.
The function below is a bit simplified version of "int_file_delete" function which
deletes a file (some comments related to nameidata were added).

int int_file_delete(const char* file_path)
{
    int os_status;
    struct dentry *dentry;
    struct nameidata nd;
    struct inode *inode = NULL;
    os_status = path_lookup(file_path, LOOKUP_PARENT, &nd); /* HERE WE FILL nameidata */
    if (os_status != 0) {
        return os_status;
    }
    if (nd.last_type != LAST_NORM) { /* HERE WE EXAMINE nameidata content */
        os_status = -EISDIR;
        goto exit;
    }
    INODE_LOCK(ND_TO_DENTRY(nd)->d_inode);
    dentry = int_lookup_hash(&nd); /* HERE WE PASS nd TO int_lookup_hash MENTIONED ABOVE */
    os_status = PTR_ERR(dentry);
    if (!IS_ERR(dentry)) {
        if (nd.last.name[nd.last.len]) { /* HERE WE EXAMINE nameidata content */
            os_status = (dentry->d_inode == NULL) ? -ENOENT : S_ISDIR(dentry->d_inode->i_mode) ? -EISDIR : -ENOTDIR;
        } else {
            inode = dentry->d_inode;
            if (inode != NULL) {
                atomic_inc(&inode->i_count);
            }
            os_status = vfs_unlink(ND_TO_DENTRY(nd)->d_inode, dentry);
        }
        dput(dentry);
    }
    INODE_UNLOCK(ND_TO_DENTRY(nd)->d_inode);
    if (inode != NULL) {
        iput(inode);
    }
  exit:
    path_release(&nd);
    if (os_status != 0) {
        return os_status;
    }
    return 0;
}

Other functions use path_lookup(), int_lookup_hash() and nameidata in a similar way.

Thanks,
Dmitry

-----Original Message-----
From: Al Viro [mailto:viro@ftp.linux.org.uk] On Behalf Of Al Viro
Sent: Tuesday, January 24, 2012 1:24 AM
To: Krivenok, Dmitry
Cc: linux-fsdevel@vger.kernel.org
Subject: Re: path_lookup() alternative

On Mon, Jan 23, 2012 at 05:19:24AM -0500, dmitry.krivenok@emc.com wrote:
> Hello,
> I sent this question to Al Viro first, but didn't get any feedback, so reposting here and hope that someone can help me.
> 
> I'm trying to build existing system consisting of several kernel modules and user-space tools on the latest vanilla kernel.
> Previously, we used path_lookup() function to perform lookup with arbitrary flags (e.g. we passed LOOKUP_PARENT in
> some cases) and save results in nameidata structure. Then, this structure was passed to other kernel functions (e.g. 
> lookup_hash and then lookup_one_len) or was used directly in the module code.

lookup_one_len() does not take nameidata at all.
lookup_hash() is not only not exported, it's _static_.

what are you talking about?

> The problem is that path_lookup() was removed in c9c6cac0c2bdbda42e7b804838648d0bc60ddb13 and kern_path_parent
> was added instead (and, of course, it didn't allow user to pass arbitrary flags).
> Then, in e3c3d9c838d48c0341c40ea45ee087e3d8c8ea39, kern_path_parent() was unexported and thus became unavailable for us.
> 
> I spent several hours learning path lookup code in the kernel tree, but didn't find a function/method which allows to get properly filled 
> nameidata having only path and flags.
> Is there an alternative to removed path_lookup() function or any other way of {path, flags}->{nameidata} translation?

Depends on what do you want to do with it.  IMO nameidata should be internal to
fs/namei.c; we still have it exposed more than I'd like it to be and if nothing
else, that exposure is going to shrink.

Details of your use case, please (ideally - along with the reference to your
code).


^ permalink raw reply	[flat|nested] 4+ messages in thread

* Re: path_lookup() alternative
  2012-01-24 13:03   ` dmitry.krivenok
@ 2012-01-24 17:19     ` Andreas Dilger
  0 siblings, 0 replies; 4+ messages in thread
From: Andreas Dilger @ 2012-01-24 17:19 UTC (permalink / raw)
  To: <dmitry.krivenok@emc.com>
  Cc: <viro@ZenIV.linux.org.uk>,
	<linux-fsdevel@vger.kernel.org>

On 2012-01-24, at 6:03, <dmitry.krivenok@emc.com> wrote:
> Hi Al, thanks for quick reply.
> 
> The module I'm working on is intended to work on wide range of kernels, so
> we have lots of #ifdefs. For example, out internal hash lookup routine looks like:
> 
> static struct dentry * int_lookup_hash(struct nameidata *nd)
> {
> #if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,15))
>    return lookup_hash(&nd->last, NDP_TO_DENTRY(nd));
> #elif (LINUX_VERSION_CODE  >= KERNEL_VERSION(2,6,16))
>    return lookup_one_len(nd->last.name, NDP_TO_DENTRY(nd), nd->last.len);
> #else
>    return lookup_hash(nd);
> #endif
> }

On a side note, from my experience the kernel version checks are nearly useless when you start trying to build against distro kernels. These kernels will backport API changes from newer upstream kernels, so you need to have autoconf checks for the specific API and symbol exports that you are concerned with.

> Where NDP_TO_DENTRY is defined as follows:
> 
> #if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,25))
> #define NDP_TO_DENTRY(_ndp) (_ndp)->path.dentry
> #else
> #define NDP_TO_DENTRY(_ndp) (_ndp)->dentry
> #endif
> 
> As you can see, lookup_hash() wasn't static is previous kernel versions.
> 
> Yes, lookup_one_len() doesn't take whole nameidata, but it may be called 
> as follows (code from drivers/base/devtmpfs.c):
> 
> kern_path_parent(name, &nd);
> ...
> dentry = lookup_one_len(nd.last.name, nd.path.dentry, nd.last.len);
> 
> That's how we call lookup_one_len() in our module and we need a way to fill 
> nameidata structure and then pass some of its fields to this function.
> path_lookup() was responsible for filling nameidata so it could then be passed
> to other kernel functions, but path_lookup() was removed.
> 
> Our module has functions which implement file/directory operations in kernel-space.
> The function below is a bit simplified version of "int_file_delete" function which
> deletes a file (some comments related to nameidata were added).
> 
> int int_file_delete(const char* file_path)
> {
>    int os_status;
>    struct dentry *dentry;
>    struct nameidata nd;
>    struct inode *inode = NULL;
>    os_status = path_lookup(file_path, LOOKUP_PARENT, &nd); /* HERE WE FILL nameidata */
>    if (os_status != 0) {
>        return os_status;
>    }
>    if (nd.last_type != LAST_NORM) { /* HERE WE EXAMINE nameidata content */
>        os_status = -EISDIR;
>        goto exit;
>    }
>    INODE_LOCK(ND_TO_DENTRY(nd)->d_inode);
>    dentry = int_lookup_hash(&nd); /* HERE WE PASS nd TO int_lookup_hash MENTIONED ABOVE */
>    os_status = PTR_ERR(dentry);
>    if (!IS_ERR(dentry)) {
>        if (nd.last.name[nd.last.len]) { /* HERE WE EXAMINE nameidata content */
>            os_status = (dentry->d_inode == NULL) ? -ENOENT : S_ISDIR(dentry->d_inode->i_mode) ? -EISDIR : -ENOTDIR;
>        } else {
>            inode = dentry->d_inode;
>            if (inode != NULL) {
>                atomic_inc(&inode->i_count);
>            }
>            os_status = vfs_unlink(ND_TO_DENTRY(nd)->d_inode, dentry);
>        }
>        dput(dentry);
>    }
>    INODE_UNLOCK(ND_TO_DENTRY(nd)->d_inode);
>    if (inode != NULL) {
>        iput(inode);
>    }
>  exit:
>    path_release(&nd);
>    if (os_status != 0) {
>        return os_status;
>    }
>    return 0;
> }
> 
> Other functions use path_lookup(), int_lookup_hash() and nameidata in a similar way.
> 
> Thanks,
> Dmitry
> 
> -----Original Message-----
> From: Al Viro [mailto:viro@ftp.linux.org.uk] On Behalf Of Al Viro
> Sent: Tuesday, January 24, 2012 1:24 AM
> To: Krivenok, Dmitry
> Cc: linux-fsdevel@vger.kernel.org
> Subject: Re: path_lookup() alternative
> 
> On Mon, Jan 23, 2012 at 05:19:24AM -0500, dmitry.krivenok@emc.com wrote:
>> Hello,
>> I sent this question to Al Viro first, but didn't get any feedback, so reposting here and hope that someone can help me.
>> 
>> I'm trying to build existing system consisting of several kernel modules and user-space tools on the latest vanilla kernel.
>> Previously, we used path_lookup() function to perform lookup with arbitrary flags (e.g. we passed LOOKUP_PARENT in
>> some cases) and save results in nameidata structure. Then, this structure was passed to other kernel functions (e.g. 
>> lookup_hash and then lookup_one_len) or was used directly in the module code.
> 
> lookup_one_len() does not take nameidata at all.
> lookup_hash() is not only not exported, it's _static_.
> 
> what are you talking about?
> 
>> The problem is that path_lookup() was removed in c9c6cac0c2bdbda42e7b804838648d0bc60ddb13 and kern_path_parent
>> was added instead (and, of course, it didn't allow user to pass arbitrary flags).
>> Then, in e3c3d9c838d48c0341c40ea45ee087e3d8c8ea39, kern_path_parent() was unexported and thus became unavailable for us.
>> 
>> I spent several hours learning path lookup code in the kernel tree, but didn't find a function/method which allows to get properly filled 
>> nameidata having only path and flags.
>> Is there an alternative to removed path_lookup() function or any other way of {path, flags}->{nameidata} translation?
> 
> Depends on what do you want to do with it.  IMO nameidata should be internal to
> fs/namei.c; we still have it exposed more than I'd like it to be and if nothing
> else, that exposure is going to shrink.
> 
> Details of your use case, please (ideally - along with the reference to your
> code).
> 
> --
> To unsubscribe from this list: send the line "unsubscribe linux-fsdevel" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply	[flat|nested] 4+ messages in thread

end of thread, other threads:[~2012-01-24 17:19 UTC | newest]

Thread overview: 4+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2012-01-23 10:19 path_lookup() alternative dmitry.krivenok
2012-01-23 21:23 ` Al Viro
2012-01-24 13:03   ` dmitry.krivenok
2012-01-24 17:19     ` Andreas Dilger

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).