lkml.org 
[lkml]   [2010]   [Jul]   [19]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    From
    Subject[PATCH -V17 07/12] vfs: Support null pathname in linkat
    Date
    This enables to use linkat to create hardlinks from a
    file descriptor pointing to the file. This can be used
    with open_by_handle syscall that returns a file descriptor.

    Signed-off-by: Aneesh Kumar K.V <aneesh.kumar@linux.vnet.ibm.com>
    ---
    fs/namei.c | 36 ++++++++++++++++++++++++++----------
    1 files changed, 26 insertions(+), 10 deletions(-)

    diff --git a/fs/namei.c b/fs/namei.c
    index 6f4f9f6..002ee3d 100644
    --- a/fs/namei.c
    +++ b/fs/namei.c
    @@ -2636,7 +2636,7 @@ int vfs_link(struct dentry *old_dentry, struct inode *dir, struct dentry *new_de
    struct inode *inode = old_dentry->d_inode;
    int error;

    - if (!inode)
    + if (!inode || inode->i_nlink == 0)
    return -ENOENT;

    error = may_create(dir, new_dentry);
    @@ -2682,16 +2682,28 @@ SYSCALL_DEFINE5(linkat, int, olddfd, const char __user *, oldname,
    {
    struct dentry *new_dentry;
    struct nameidata nd;
    - struct path old_path;
    - int error;
    + struct path old_path, *old_pathp;
    + struct file *file = NULL;
    + int error, fput_needed;
    char *to;

    if ((flags & ~AT_SYMLINK_FOLLOW) != 0)
    return -EINVAL;

    - error = user_path_at(olddfd, oldname,
    - flags & AT_SYMLINK_FOLLOW ? LOOKUP_FOLLOW : 0,
    - &old_path);
    + if (oldname == NULL && olddfd != AT_FDCWD) {
    + file = fget_light(olddfd, &fput_needed);
    + if (file) {
    + old_pathp = &file->f_path;
    + error = 0;
    + } else
    + error = -EBADF;
    + } else {
    + error = user_path_at(olddfd, oldname,
    + flags & AT_SYMLINK_FOLLOW ?
    + LOOKUP_FOLLOW : 0,
    + &old_path);
    + old_pathp = &old_path;
    + }
    if (error)
    return error;

    @@ -2699,7 +2711,7 @@ SYSCALL_DEFINE5(linkat, int, olddfd, const char __user *, oldname,
    if (error)
    goto out;
    error = -EXDEV;
    - if (old_path.mnt != nd.path.mnt)
    + if (old_pathp->mnt != nd.path.mnt)
    goto out_release;
    new_dentry = lookup_create(&nd, 0);
    error = PTR_ERR(new_dentry);
    @@ -2708,10 +2720,11 @@ SYSCALL_DEFINE5(linkat, int, olddfd, const char __user *, oldname,
    error = mnt_want_write(nd.path.mnt);
    if (error)
    goto out_dput;
    - error = security_path_link(old_path.dentry, &nd.path, new_dentry);
    + error = security_path_link(old_pathp->dentry, &nd.path, new_dentry);
    if (error)
    goto out_drop_write;
    - error = vfs_link(old_path.dentry, nd.path.dentry->d_inode, new_dentry);
    + error = vfs_link(old_pathp->dentry,
    + nd.path.dentry->d_inode, new_dentry);
    out_drop_write:
    mnt_drop_write(nd.path.mnt);
    out_dput:
    @@ -2722,7 +2735,10 @@ out_release:
    path_put(&nd.path);
    putname(to);
    out:
    - path_put(&old_path);
    + if (file)
    + fput_light(file, fput_needed);
    + else
    + path_put(&old_path);

    return error;
    }
    --
    1.7.2.rc3.43.g24e7a


    \
     
     \ /
      Last update: 2010-07-19 21:17    [W:0.025 / U:63.432 seconds]
    ©2003-2016 Jasper Spaans. hosted at Digital OceanAdvertise on this site