From patchwork Tue Apr 21 19:56:10 2015 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Eric Van Hensbergen X-Patchwork-Id: 6252761 Return-Path: X-Original-To: patchwork-v9fs-devel@patchwork.kernel.org Delivered-To: patchwork-parsemail@patchwork1.web.kernel.org Received: from mail.kernel.org (mail.kernel.org [198.145.29.136]) by patchwork1.web.kernel.org (Postfix) with ESMTP id 2DFA89F32B for ; Tue, 21 Apr 2015 19:56:49 +0000 (UTC) Received: from mail.kernel.org (localhost [127.0.0.1]) by mail.kernel.org (Postfix) with ESMTP id 3633C202F0 for ; Tue, 21 Apr 2015 19:56:48 +0000 (UTC) Received: from lists.sourceforge.net (lists.sourceforge.net [216.34.181.88]) (using TLSv1 with cipher DHE-RSA-AES256-SHA (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPS id ECB01202D1 for ; Tue, 21 Apr 2015 19:56:46 +0000 (UTC) Received: from localhost ([127.0.0.1] helo=sfs-ml-2.v29.ch3.sourceforge.com) by sfs-ml-2.v29.ch3.sourceforge.com with esmtp (Exim 4.76) (envelope-from ) id 1YkeHe-0002ZL-0e; Tue, 21 Apr 2015 19:56:38 +0000 Received: from sog-mx-2.v43.ch3.sourceforge.com ([172.29.43.192] helo=mx.sourceforge.net) by sfs-ml-2.v29.ch3.sourceforge.com with esmtp (Exim 4.76) (envelope-from ) id 1YkeHd-0002ZC-31 for v9fs-developer@lists.sourceforge.net; Tue, 21 Apr 2015 19:56:37 +0000 Received-SPF: pass (sog-mx-2.v43.ch3.sourceforge.com: domain of gmail.com designates 209.85.214.182 as permitted sender) client-ip=209.85.214.182; envelope-from=ericvh@gmail.com; helo=mail-ob0-f182.google.com; Received: from mail-ob0-f182.google.com ([209.85.214.182]) by sog-mx-2.v43.ch3.sourceforge.com with esmtps (TLSv1:RC4-SHA:128) (Exim 4.76) id 1YkeHc-000353-2P for v9fs-developer@lists.sourceforge.net; Tue, 21 Apr 2015 19:56:37 +0000 Received: by obbeb7 with SMTP id eb7so153720764obb.3 for ; Tue, 21 Apr 2015 12:56:30 -0700 (PDT) X-Received: by 10.182.165.69 with SMTP id yw5mr20072599obb.5.1429646190579; Tue, 21 Apr 2015 12:56:30 -0700 (PDT) MIME-Version: 1.0 Received: by 10.202.197.135 with HTTP; Tue, 21 Apr 2015 12:56:10 -0700 (PDT) From: Eric Van Hensbergen Date: Tue, 21 Apr 2015 14:56:10 -0500 Message-ID: To: V9FS Developers X-Spam-Score: -1.6 (-) X-Headers-End: 1YkeHc-000353-2P Subject: [V9fs-developer] [PATCH] fs/9p: fix create-unlink-getattr idiom X-BeenThere: v9fs-developer@lists.sourceforge.net X-Mailman-Version: 2.1.9 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: v9fs-developer-bounces@lists.sourceforge.net X-Spam-Status: No, score=-6.9 required=5.0 tests=BAYES_00, DKIM_ADSP_CUSTOM_MED, FREEMAIL_FROM,RCVD_IN_DNSWL_HI,T_RP_MATCHES_RCVD,UNPARSEABLE_RELAY autolearn=unavailable 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 Fixes several outstanding bug reports of not being able to getattr from an open file after an unlink. This patch cleans up transient fids on an unlink and will search open fids on a client if it detects a dentry that appears to have been unlinked. This search is necessary because fstat does not pass fd information through the VFS API to the filesystem, only the dentry which for 9p has an imperfect match to fids. Inherent in this patch is also a fix for the qid handling on create/open which apparently wasn't being set correctly and was necessary for the search to succeed. A possible optimization over this fix is to include accounting of open fids with the inode in the private data (in a similar fashion to the way we track transient fids with dentries). This would allow a much quicker search for a matching open fid. Signed-off-by: Eric Van Hensbergen --- fs/9p/fid.c | 30 ++++++++++++++++++++++++++++++ fs/9p/vfs_inode.c | 4 ++++ fs/9p/vfs_inode_dotl.c | 11 +++++++---- net/9p/client.c | 6 ++++-- 4 files changed, 45 insertions(+), 6 deletions(-) return fid; @@ -1266,6 +1266,7 @@ int p9_client_open(struct p9_fid *fid, int mode) p9_is_proto_dotl(clnt) ? "RLOPEN" : "ROPEN", qid.type, (unsigned long long)qid.path, qid.version, iounit); + memmove(&fid->qid, &qid, sizeof(struct p9_qid)); fid->mode = mode; fid->iounit = iounit; @@ -1311,6 +1312,7 @@ int p9_client_create_dotl(struct p9_fid *ofid, char *name, u32 flags, u32 mode, (unsigned long long)qid->path, qid->version, iounit); + memmove(&ofid->qid, qid, sizeof(struct p9_qid)); ofid->mode = mode; ofid->iounit = iounit; @@ -1356,9 +1358,9 @@ int p9_client_fcreate(struct p9_fid *fid, char *name, u32 perm, int mode, (unsigned long long)qid.path, qid.version, iounit); + memmove(&fid->qid, &qid, sizeof(struct p9_qid)); fid->mode = mode; fid->iounit = iounit; - free_and_error: p9_free_req(clnt, req); error: diff --git a/fs/9p/fid.c b/fs/9p/fid.c index 47db55a..5ca6e67 100644 --- a/fs/9p/fid.c +++ b/fs/9p/fid.c @@ -54,6 +54,33 @@ void v9fs_fid_add(struct dentry *dentry, struct p9_fid *fid) } /** + * v9fs_fid_find_global - search for a fid off of the client list + * @inode: return a fid pointing to a specific inode + * @uid: return a fid belonging to the specified user + * + */ + +static struct p9_fid *v9fs_fid_find_inode(struct inode *inode, kuid_t uid) +{ + struct p9_client *clnt = v9fs_inode2v9ses(inode)->clnt; + struct p9_fid *fid, *fidptr, *ret = NULL; + unsigned long flags; + + p9_debug(P9_DEBUG_VFS, " inode: %p\n", inode); + + spin_lock_irqsave(&clnt->lock, flags); + list_for_each_entry_safe(fid, fidptr, &clnt->fidlist, flist) { + if (uid_eq(fid->uid, uid) && + (inode->i_ino == v9fs_qid2ino(&fid->qid))) { + ret = fid; + break; + } + } + spin_unlock_irqrestore(&clnt->lock, flags); + return ret; +} + +/** * v9fs_fid_find - retrieve a fid that belongs to the specified uid * @dentry: dentry to look for fid in * @uid: return fid that belongs to the specified user @@ -80,6 +107,9 @@ static struct p9_fid *v9fs_fid_find(struct dentry *dentry, kuid_t uid, int any) } } spin_unlock(&dentry->d_lock); + } else { + if (dentry->d_inode) + ret = v9fs_fid_find_inode(dentry->d_inode, uid); } return ret; diff --git a/fs/9p/vfs_inode.c b/fs/9p/vfs_inode.c index 3662f1d..7405149 100644 --- a/fs/9p/vfs_inode.c +++ b/fs/9p/vfs_inode.c @@ -625,6 +625,10 @@ static int v9fs_remove(struct inode *dir, struct dentry *dentry, int flags) v9fs_invalidate_inode_attr(inode); v9fs_invalidate_inode_attr(dir); + + /* invalidate all fids associated with dentry */ + /* NOTE: This will not include open fids */ + dentry->d_op->d_release(dentry); } return retval; } diff --git a/fs/9p/vfs_inode_dotl.c b/fs/9p/vfs_inode_dotl.c index 6054c16b..ab9c49e 100644 --- a/fs/9p/vfs_inode_dotl.c +++ b/fs/9p/vfs_inode_dotl.c @@ -475,7 +475,7 @@ v9fs_vfs_getattr_dotl(struct vfsmount *mnt, struct dentry *dentry, struct kstat *stat) { struct v9fs_session_info *v9ses; - struct p9_fid *fid; + struct p9_fid *fid = NULL; struct p9_stat_dotl *st; p9_debug(P9_DEBUG_VFS, "dentry: %p\n", dentry); @@ -484,9 +484,12 @@ v9fs_vfs_getattr_dotl(struct vfsmount *mnt, struct dentry *dentry, generic_fillattr(dentry->d_inode, stat); return 0; } - fid = v9fs_fid_lookup(dentry); - if (IS_ERR(fid)) - return PTR_ERR(fid); + + if (fid == NULL) { + fid = v9fs_fid_lookup(dentry); + if (IS_ERR(fid)) + return PTR_ERR(fid); + } /* Ask for all the fields in stat structure. Server will return * whatever it supports diff --git a/net/9p/client.c b/net/9p/client.c index e86a9be..2ff06dd 100644 --- a/net/9p/client.c +++ b/net/9p/client.c @@ -1213,7 +1213,7 @@ struct p9_fid *p9_client_walk(struct p9_fid *oldfid, uint16_t nwname, if (nwname) memmove(&fid->qid, &wqids[nwqids - 1], sizeof(struct p9_qid)); else - fid->qid = oldfid->qid; + memmove(&fid->qid, &oldfid->qid, sizeof(struct p9_qid)); kfree(wqids);