RE: path_lookup() alternative

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



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@xxxxxxxxxxxxxxxx] On Behalf Of Al Viro
Sent: Tuesday, January 24, 2012 1:24 AM
To: Krivenok, Dmitry
Cc: linux-fsdevel@xxxxxxxxxxxxxxx
Subject: Re: path_lookup() alternative

On Mon, Jan 23, 2012 at 05:19:24AM -0500, dmitry.krivenok@xxxxxxx 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@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[Index of Archives]     [Linux Ext4 Filesystem]     [Union Filesystem]     [Filesystem Testing]     [Ceph Users]     [Ecryptfs]     [AutoFS]     [Kernel Newbies]     [Share Photos]     [Security]     [Netfilter]     [Bugtraq]     [Yosemite News]     [MIPS Linux]     [ARM Linux]     [Linux Security]     [Linux Cachefs]     [Reiser Filesystem]     [Linux RAID]     [Samba]     [Device Mapper]     [CEPH Development]
  Powered by Linux