From mboxrd@z Thu Jan 1 00:00:00 1970 From: Valerie Aurora Subject: [PATCH 65/74] union-mount: Implement union-aware link() Date: Tue, 22 Mar 2011 19:04:56 -0700 Message-ID: <1300845905-14433-22-git-send-email-valerie.aurora@gmail.com> References: <1300845905-14433-1-git-send-email-valerie.aurora@gmail.com> Cc: viro@zeniv.linux.org.uk, Valerie Aurora , Valerie Aurora To: linux-fsdevel@vger.kernel.org, linux@vger.kernel.org Return-path: Received: from mail-yw0-f46.google.com ([209.85.213.46]:40111 "EHLO mail-yw0-f46.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1755215Ab1CWCGM (ORCPT ); Tue, 22 Mar 2011 22:06:12 -0400 In-Reply-To: <1300845905-14433-1-git-send-email-valerie.aurora@gmail.com> Sender: linux-fsdevel-owner@vger.kernel.org List-ID: From: Valerie Aurora Signed-off-by: Valerie Aurora --- fs/namei.c | 24 ++++++++++++++++++++---- 1 files changed, 20 insertions(+), 4 deletions(-) diff --git a/fs/namei.c b/fs/namei.c index 5eec62c..6ea9cdc 100644 --- a/fs/namei.c +++ b/fs/namei.c @@ -2976,16 +2976,18 @@ SYSCALL_DEFINE5(linkat, int, olddfd, const char __user *, oldname, { struct dentry *new_dentry; struct nameidata nd; + struct nameidata old_nd; struct path old_path; int error; char *to; + char *from; if ((flags & ~AT_SYMLINK_FOLLOW) != 0) return -EINVAL; - error = user_path_at(olddfd, oldname, + error = user_path_nd(olddfd, oldname, flags & AT_SYMLINK_FOLLOW ? LOOKUP_FOLLOW : 0, - &old_path); + &old_nd, &old_path, &from); if (error) return error; @@ -2993,8 +2995,20 @@ SYSCALL_DEFINE5(linkat, int, olddfd, const char __user *, oldname, if (error) goto out; error = -EXDEV; - if (old_path.mnt != nd.path.mnt) - goto out_release; + if (old_path.mnt != nd.path.mnt) { + if (IS_DIR_UNIONED(old_nd.path.dentry) && + (old_nd.path.mnt == nd.path.mnt)) { + error = mnt_want_write(old_nd.path.mnt); + if (error) + goto out_release; + error = union_copyup(&old_nd, &old_path); + mnt_drop_write(old_nd.path.mnt); + if (error) + goto out_release; + } else { + goto out_release; + } + } new_dentry = lookup_create(&nd, 0); error = PTR_ERR(new_dentry); if (IS_ERR(new_dentry)) @@ -3017,6 +3031,8 @@ out_release: putname(to); out: path_put(&old_path); + path_put(&old_nd.path); + putname(from); return error; } -- 1.7.0.4