From patchwork Wed Feb 26 19:52:33 2014 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Shirish Pargaonkar X-Patchwork-Id: 3728301 Return-Path: X-Original-To: patchwork-cifs-client@patchwork.kernel.org Delivered-To: patchwork-parsemail@patchwork1.web.kernel.org Received: from mail.kernel.org (mail.kernel.org [198.145.19.201]) by patchwork1.web.kernel.org (Postfix) with ESMTP id BBB3B9F2ED for ; Wed, 26 Feb 2014 19:52:51 +0000 (UTC) Received: from mail.kernel.org (localhost [127.0.0.1]) by mail.kernel.org (Postfix) with ESMTP id BFFAB201CD for ; Wed, 26 Feb 2014 19:52:50 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.kernel.org (Postfix) with ESMTP id D1D9120166 for ; Wed, 26 Feb 2014 19:52:49 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1753750AbaBZTwt (ORCPT ); Wed, 26 Feb 2014 14:52:49 -0500 Received: from mail-ob0-f176.google.com ([209.85.214.176]:61922 "EHLO mail-ob0-f176.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1753637AbaBZTws (ORCPT ); Wed, 26 Feb 2014 14:52:48 -0500 Received: by mail-ob0-f176.google.com with SMTP id wo20so1299634obc.35 for ; Wed, 26 Feb 2014 11:52:46 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20120113; h=from:to:cc:subject:date:message-id; bh=kUwXsq8YKBHRKHjRJ4gba1QiU02UjxAEnQJXSoS2jkk=; b=jlRFjo0qKFQEos8Lkk4m5IvyTtjs+a5yDZb+Nmy0/2Ej/vxXoIZ/XJumwqcRvB7sOZ C9ePlNQVeDsb1vc4jFDyAFNGceRvvEVnfP6KxmOFvojprgpW97vp24HvnKwHW573UP0u 3pHPB0/8OenGwylcvFsllXn+nv4mFR3uB68V1fi2s/VbYCY4zBRAj/C9SxHM5hiqGNjY ecmkjK7cBQCa87O8cBCQMfuo3abhVME+D3WjY7/FZfw9X0Ja+ANmAa/hLnIL9Q9fhBKr SKFhFPT4xr9pt9nwDRWnjXzvCvrDZS2R6y1X69kZOdc4eOk/hiryMpdAiqyJG+/wqQTn JlLQ== X-Received: by 10.60.98.73 with SMTP id eg9mr1882001oeb.81.1393444366099; Wed, 26 Feb 2014 11:52:46 -0800 (PST) Received: from shirish-ThinkPad-T400.gns.novell.com (75-13-85-90.lightspeed.austtx.sbcglobal.net. [75.13.85.90]) by mx.google.com with ESMTPSA id g4sm4328666obe.5.2014.02.26.11.52.44 for (version=TLSv1.1 cipher=ECDHE-RSA-RC4-SHA bits=128/128); Wed, 26 Feb 2014 11:52:44 -0800 (PST) From: shirishpargaonkar@gmail.com To: sfrench@gmail.com Cc: linux-cifs@vger.kernel.org, Shirish Pargaonkar Subject: [PATCH] cifs: Allow mounts with restricted intermediate paths (try #2) Date: Wed, 26 Feb 2014 13:52:33 -0600 Message-Id: <1393444353-10343-1-git-send-email-spargaonkar@suse.com> X-Mailer: git-send-email 1.8.3.2 Sender: linux-cifs-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-cifs@vger.kernel.org X-Spam-Status: No, score=-6.8 required=5.0 tests=BAYES_00, DKIM_ADSP_CUSTOM_MED, DKIM_SIGNED, FREEMAIL_FROM, RCVD_IN_DNSWL_HI, RP_MATCHES_RCVD, T_DKIM_INVALID, UNPARSEABLE_RELAY autolearn=ham version=3.3.1 X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on mail.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP From: Shirish Pargaonkar Allow mounts with intermediate paths without access. Create an anonymous root dentry for a vfsmount with an inode obtained via path info if any of the intermediate path entries are not accessible with EACCES error. If this dentry becomes accessible via other mounts, splice this anonymous root dentry (and the subtree under it) at the appropriate place in that mount. Reference: Samba bugzilla 6950 Signed-off-by: Shirish Pargaonkar --- fs/cifs/cifsfs.c | 25 +++++++++++++++++++++++-- fs/cifs/dir.c | 18 ++++++++++++++---- fs/cifs/inode.c | 6 ++++-- 3 files changed, 41 insertions(+), 8 deletions(-) diff --git a/fs/cifs/cifsfs.c b/fs/cifs/cifsfs.c index 849f613..35a7a80 100644 --- a/fs/cifs/cifsfs.c +++ b/fs/cifs/cifsfs.c @@ -584,9 +584,12 @@ cifs_get_root(struct smb_vol *vol, struct super_block *sb) char *full_path = NULL; char *s, *p; char sep; + int rc; + unsigned int xid; + struct inode *rinode = NULL; + struct cifs_tcon *tcon = cifs_sb_master_tcon(cifs_sb); - full_path = cifs_build_path_to_root(vol, cifs_sb, - cifs_sb_master_tcon(cifs_sb)); + full_path = cifs_build_path_to_root(vol, cifs_sb, tcon); if (full_path == NULL) return ERR_PTR(-ENOMEM); @@ -627,6 +630,24 @@ cifs_get_root(struct smb_vol *vol, struct super_block *sb) dput(dentry); dentry = child; } while (!IS_ERR(dentry)); + if (IS_ERR(dentry) && (PTR_ERR(dentry) == -EACCES) && *s) { + xid = get_xid(); + if (tcon->unix_ext) { + rc = cifs_get_inode_info_unix(&rinode, full_path, + sb, xid); + } else { + rc = cifs_get_inode_info(&rinode, full_path, NULL, + sb, xid, NULL); + } + free_xid(xid); + + if ((rc == 0) && (rinode != NULL)) { + dentry = d_obtain_alias(rinode); + if (IS_ERR(dentry)) + iput(rinode); + } + } + kfree(full_path); return dentry; } diff --git a/fs/cifs/dir.c b/fs/cifs/dir.c index 3db0c5f..7eb8ccc 100644 --- a/fs/cifs/dir.c +++ b/fs/cifs/dir.c @@ -702,6 +702,7 @@ cifs_lookup(struct inode *parent_dir_inode, struct dentry *direntry, struct cifs_tcon *pTcon; struct inode *newInode = NULL; char *full_path = NULL; + struct dentry *ret = NULL; xid = get_xid(); @@ -748,11 +749,19 @@ cifs_lookup(struct inode *parent_dir_inode, struct dentry *direntry, } if ((rc == 0) && (newInode != NULL)) { - d_add(direntry, newInode); /* since paths are not looked up by component - the parent directories are presumed to be good here */ - renew_parental_timestamps(direntry); - + ret = d_splice_alias(newInode, direntry); + if (!ret) + renew_parental_timestamps(direntry); + else { + if (!IS_ERR(ret)) { + renew_parental_timestamps(direntry); + dput(ret); + goto lookup_out; + } else + rc = PTR_ERR(ret); + } } else if (rc == -ENOENT) { rc = 0; direntry->d_time = jiffies; @@ -764,12 +773,13 @@ cifs_lookup(struct inode *parent_dir_inode, struct dentry *direntry, /* We special case check for Access Denied - since that is a common return code */ } + ret = ERR_PTR(rc); lookup_out: kfree(full_path); cifs_put_tlink(tlink); free_xid(xid); - return ERR_PTR(rc); + return ret; } static int diff --git a/fs/cifs/inode.c b/fs/cifs/inode.c index aadc2b6..00006ab 100644 --- a/fs/cifs/inode.c +++ b/fs/cifs/inode.c @@ -885,8 +885,10 @@ inode_has_hashed_dentries(struct inode *inode) spin_lock(&inode->i_lock); hlist_for_each_entry(dentry, &inode->i_dentry, d_alias) { if (!d_unhashed(dentry) || IS_ROOT(dentry)) { - spin_unlock(&inode->i_lock); - return true; + if (!(dentry->d_flags & DCACHE_DISCONNECTED)) { + spin_unlock(&inode->i_lock); + return true; + } } } spin_unlock(&inode->i_lock);