From 154372e67d4053e56591245eb413686621941333 Mon Sep 17 00:00:00 2001 From: Eric Van Hensbergen Date: Wed, 23 Sep 2020 22:11:43 +0800 Subject: fs/9p: fix create-unlink-getattr idiom 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. (changed v9fs_fid_find_global to v9fs_fid_find_inode in comment) Link: http://lkml.kernel.org/r/20200923141146.90046-2-jianyong.wu@arm.com Signed-off-by: Eric Van Hensbergen Signed-off-by: Greg Kurz Signed-off-by: Jianyong Wu Signed-off-by: Dominique Martinet --- net/9p/client.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) (limited to 'net/9p') diff --git a/net/9p/client.c b/net/9p/client.c index 09f1ec589b80..1a3f72bf45fc 100644 --- a/net/9p/client.c +++ b/net/9p/client.c @@ -1219,7 +1219,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); return fid; @@ -1272,6 +1272,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; @@ -1317,6 +1318,7 @@ int p9_client_create_dotl(struct p9_fid *ofid, const char *name, u32 flags, u32 (unsigned long long)qid->path, qid->version, iounit); + memmove(&ofid->qid, qid, sizeof(struct p9_qid)); ofid->mode = mode; ofid->iounit = iounit; @@ -1362,6 +1364,7 @@ int p9_client_fcreate(struct p9_fid *fid, const 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; -- cgit v1.2.3