From 6e0149a55379d6b91948cf6e94e700eb7dbaa518 Mon Sep 17 00:00:00 2001 From: Christophe JAILLET Date: Sun, 27 Nov 2022 13:59:25 +0100 Subject: 9p/fs: Remove unneeded idr.h #include The 9p fs does not use IDR or IDA functionalities. So there is no point in including . Remove it. Link: https://lkml.kernel.org/r/3d1e0ed9714eaee7e18d9f5b0b4bfa49b00b286d.1669553950.git.christophe.jaillet@wanadoo.fr Signed-off-by: Christophe JAILLET Reviewed-by: Christian Schoenebeck [Dominique: reword subject] Signed-off-by: Dominique Martinet --- fs/9p/fid.c | 1 - fs/9p/v9fs.c | 1 - fs/9p/vfs_addr.c | 1 - fs/9p/vfs_dentry.c | 1 - fs/9p/vfs_dir.c | 1 - fs/9p/vfs_file.c | 1 - fs/9p/vfs_inode.c | 1 - fs/9p/vfs_inode_dotl.c | 1 - fs/9p/vfs_super.c | 1 - 9 files changed, 9 deletions(-) diff --git a/fs/9p/fid.c b/fs/9p/fid.c index 23cf9b2fbfe4..805151114e96 100644 --- a/fs/9p/fid.c +++ b/fs/9p/fid.c @@ -11,7 +11,6 @@ #include #include #include -#include #include #include diff --git a/fs/9p/v9fs.c b/fs/9p/v9fs.c index 0129de2ea31a..3a9c4517265f 100644 --- a/fs/9p/v9fs.c +++ b/fs/9p/v9fs.c @@ -14,7 +14,6 @@ #include #include #include -#include #include #include #include diff --git a/fs/9p/vfs_addr.c b/fs/9p/vfs_addr.c index 47b9a1122f34..93373486ab04 100644 --- a/fs/9p/vfs_addr.c +++ b/fs/9p/vfs_addr.c @@ -14,7 +14,6 @@ #include #include #include -#include #include #include #include diff --git a/fs/9p/vfs_dentry.c b/fs/9p/vfs_dentry.c index f89f01734587..65fa2df5e49b 100644 --- a/fs/9p/vfs_dentry.c +++ b/fs/9p/vfs_dentry.c @@ -15,7 +15,6 @@ #include #include #include -#include #include #include #include diff --git a/fs/9p/vfs_dir.c b/fs/9p/vfs_dir.c index 000fbaae9b18..1675a196c2ba 100644 --- a/fs/9p/vfs_dir.c +++ b/fs/9p/vfs_dir.c @@ -14,7 +14,6 @@ #include #include #include -#include #include #include #include diff --git a/fs/9p/vfs_file.c b/fs/9p/vfs_file.c index aec43ba83799..b740017634ef 100644 --- a/fs/9p/vfs_file.c +++ b/fs/9p/vfs_file.c @@ -18,7 +18,6 @@ #include #include #include -#include #include #include #include diff --git a/fs/9p/vfs_inode.c b/fs/9p/vfs_inode.c index 4d1a4a8d9277..27a04a226d97 100644 --- a/fs/9p/vfs_inode.c +++ b/fs/9p/vfs_inode.c @@ -17,7 +17,6 @@ #include #include #include -#include #include #include #include diff --git a/fs/9p/vfs_inode_dotl.c b/fs/9p/vfs_inode_dotl.c index 5cfa4b4f070f..8696e8899c27 100644 --- a/fs/9p/vfs_inode_dotl.c +++ b/fs/9p/vfs_inode_dotl.c @@ -15,7 +15,6 @@ #include #include #include -#include #include #include #include diff --git a/fs/9p/vfs_super.c b/fs/9p/vfs_super.c index 2d9ee073d12c..266c4693e20c 100644 --- a/fs/9p/vfs_super.c +++ b/fs/9p/vfs_super.c @@ -15,7 +15,6 @@ #include #include #include -#include #include #include #include -- cgit v1.2.3 From 31fff92c9cadbca4cd294bcdff285ca3fc9bad7c Mon Sep 17 00:00:00 2001 From: Christophe JAILLET Date: Sun, 27 Nov 2022 15:46:45 +0100 Subject: 9p/net: Remove unneeded idr.h #include The 9p net files don't use IDR or IDA functionalities. So there is no point in including . Remove it. Link: https://lkml.kernel.org/r/9e386018601d7e4a9e5d7da8fc3e9555ebb25c87.1669560387.git.christophe.jaillet@wanadoo.fr Signed-off-by: Christophe JAILLET Reviewed-by: Christian Schoenebeck Signed-off-by: Dominique Martinet --- net/9p/trans_fd.c | 1 - net/9p/trans_rdma.c | 1 - net/9p/trans_virtio.c | 1 - 3 files changed, 3 deletions(-) diff --git a/net/9p/trans_fd.c b/net/9p/trans_fd.c index eeea0a6a75b6..06ec9f7d3318 100644 --- a/net/9p/trans_fd.c +++ b/net/9p/trans_fd.c @@ -20,7 +20,6 @@ #include #include #include -#include #include #include #include diff --git a/net/9p/trans_rdma.c b/net/9p/trans_rdma.c index 6ff706760676..33a9ac6f2d55 100644 --- a/net/9p/trans_rdma.c +++ b/net/9p/trans_rdma.c @@ -21,7 +21,6 @@ #include #include #include -#include #include #include #include diff --git a/net/9p/trans_virtio.c b/net/9p/trans_virtio.c index e757f0601304..19bccfa0d593 100644 --- a/net/9p/trans_virtio.c +++ b/net/9p/trans_virtio.c @@ -22,7 +22,6 @@ #include #include #include -#include #include #include #include -- cgit v1.2.3 From 26273ade77f54716e30dfd40ac6e85ceb54ac0f9 Mon Sep 17 00:00:00 2001 From: Schspa Shi Date: Thu, 1 Dec 2022 11:33:10 +0800 Subject: 9p: set req refcount to zero to avoid uninitialized usage When a new request is allocated, the refcount will be zero if it is reused, but if the request is newly allocated from slab, it is not fully initialized before being added to idr. If the p9_read_work got a response before the refcount initiated. It will use a uninitialized req, which will result in a bad request data struct. Here is the logs from syzbot. Corrupted memory at 0xffff88807eade00b [ 0xff 0x07 0x00 0x00 0x00 0x00 0x00 0x00 . . . . . . . . ] (in kfence-#110): p9_fcall_fini net/9p/client.c:248 [inline] p9_req_put net/9p/client.c:396 [inline] p9_req_put+0x208/0x250 net/9p/client.c:390 p9_client_walk+0x247/0x540 net/9p/client.c:1165 clone_fid fs/9p/fid.h:21 [inline] v9fs_fid_xattr_set+0xe4/0x2b0 fs/9p/xattr.c:118 v9fs_xattr_set fs/9p/xattr.c:100 [inline] v9fs_xattr_handler_set+0x6f/0x120 fs/9p/xattr.c:159 __vfs_setxattr+0x119/0x180 fs/xattr.c:182 __vfs_setxattr_noperm+0x129/0x5f0 fs/xattr.c:216 __vfs_setxattr_locked+0x1d3/0x260 fs/xattr.c:277 vfs_setxattr+0x143/0x340 fs/xattr.c:309 setxattr+0x146/0x160 fs/xattr.c:617 path_setxattr+0x197/0x1c0 fs/xattr.c:636 __do_sys_setxattr fs/xattr.c:652 [inline] __se_sys_setxattr fs/xattr.c:648 [inline] __ia32_sys_setxattr+0xc0/0x160 fs/xattr.c:648 do_syscall_32_irqs_on arch/x86/entry/common.c:112 [inline] __do_fast_syscall_32+0x65/0xf0 arch/x86/entry/common.c:178 do_fast_syscall_32+0x33/0x70 arch/x86/entry/common.c:203 entry_SYSENTER_compat_after_hwframe+0x70/0x82 Below is a similar scenario, the scenario in the syzbot log looks more complicated than this one, but this patch can fix it. T21124 p9_read_work ======================== second trans ================================= p9_client_walk p9_client_rpc p9_client_prepare_req p9_tag_alloc req = kmem_cache_alloc(p9_req_cache, GFP_NOFS); tag = idr_alloc << preempted >> req->tc.tag = tag; /* req->[refcount/tag] == uninitialized */ m->rreq = p9_tag_lookup(m->client, m->rc.tag); /* increments uninitalized refcount */ refcount_set(&req->refcount, 2); /* cb drops one ref */ p9_client_cb(req) /* reader thread drops its ref: request is incorrectly freed */ p9_req_put(req) /* use after free and ref underflow */ p9_req_put(req) To fix it, we can initialize the refcount to zero before add to idr. Link: https://lkml.kernel.org/r/20221201033310.18589-1-schspa@gmail.com Cc: stable@vger.kernel.org # 6.0+ due to 6cda12864cb0 ("9p: Drop kref usage") Fixes: 728356dedeff ("9p: Add refcount to p9_req_t") Reported-by: syzbot+8f1060e2aaf8ca55220b@syzkaller.appspotmail.com Signed-off-by: Schspa Shi Reviewed-by: Christian Schoenebeck Signed-off-by: Dominique Martinet --- net/9p/client.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/net/9p/client.c b/net/9p/client.c index aaa37b07e30a..b554f8357f96 100644 --- a/net/9p/client.c +++ b/net/9p/client.c @@ -297,6 +297,11 @@ p9_tag_alloc(struct p9_client *c, int8_t type, uint t_size, uint r_size, p9pdu_reset(&req->rc); req->t_err = 0; req->status = REQ_STATUS_ALLOC; + /* refcount needs to be set to 0 before inserting into the idr + * so p9_tag_lookup does not accept a request that is not fully + * initialized. refcount_set to 2 below will mark request ready. + */ + refcount_set(&req->refcount, 0); init_waitqueue_head(&req->wq); INIT_LIST_HEAD(&req->req_list); -- cgit v1.2.3 From f15e006b831384aaec4b4f13265c0dff88ef09dd Mon Sep 17 00:00:00 2001 From: Dominique Martinet Date: Tue, 22 Nov 2022 09:06:56 +0900 Subject: 9p/xen: do not memcpy header into req->rc while 'h' is packed and can be assumed to match the request payload, req->rc is a struct p9_fcall which is not packed and that memcpy could be wrong. Fix this by copying each fields individually instead. Reported-by: Christian Schoenebeck Reviewed-by: Christian Schoenebeck Suggested-by: Stefano Stabellini Reviewed-by: Stefano Stabellini Link: https://lkml.kernel.org/r/alpine.DEB.2.22.394.2211211454540.1049131@ubuntu-linux-20-04-desktop Link: https://lkml.kernel.org/r/20221122001025.119121-1-asmadeus@codewreck.org Signed-off-by: Dominique Martinet --- net/9p/trans_xen.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/net/9p/trans_xen.c b/net/9p/trans_xen.c index aaa5fd364691..de2d2ca8819a 100644 --- a/net/9p/trans_xen.c +++ b/net/9p/trans_xen.c @@ -216,7 +216,9 @@ static void p9_xen_response(struct work_struct *work) goto recv_error; } - memcpy(&req->rc, &h, sizeof(h)); + req->rc.size = h.size; + req->rc.id = h.id; + req->rc.tag = h.tag; req->rc.offset = 0; masked_cons = xen_9pfs_mask(cons, XEN_9PFS_RING_SIZE(ring)); -- cgit v1.2.3 From 8e4c2eee1e15c1206c26f6b28b05fe9711a427c6 Mon Sep 17 00:00:00 2001 From: Christian Schoenebeck Date: Tue, 22 Nov 2022 20:20:22 +0100 Subject: net/9p: distinguish zero-copy requests Add boolean `zc` member to struct p9_fcall to distinguish zero-copy messages (not using the linear `sdata` buffer for message payload) from regular messages (which do copy message payload to `sdata` before being further processed). This new member is appended to end of structure to avoid inserting huge padding in generated layout. Link: https://lkml.kernel.org/r/8f2a5c12a446c3b544da64e0b1550e1fb2d6f972.1669144861.git.linux_oss@crudebyte.com Signed-off-by: Christian Schoenebeck Tested-by: Stefano Stabellini Signed-off-by: Dominique Martinet --- include/net/9p/9p.h | 2 ++ net/9p/client.c | 6 ++++++ 2 files changed, 8 insertions(+) diff --git a/include/net/9p/9p.h b/include/net/9p/9p.h index 13abe013af21..429adf6be29c 100644 --- a/include/net/9p/9p.h +++ b/include/net/9p/9p.h @@ -531,6 +531,7 @@ struct p9_rstatfs { * @offset: used by marshalling routines to track current position in buffer * @capacity: used by marshalling routines to track total malloc'd capacity * @sdata: payload + * @zc: whether zero-copy is used * * &p9_fcall represents the structure for all 9P RPC * transactions. Requests are packaged into fcalls, and reponses @@ -549,6 +550,7 @@ struct p9_fcall { struct kmem_cache *cache; u8 *sdata; + bool zc; }; int p9_errstr2errno(char *errstr, int len); diff --git a/net/9p/client.c b/net/9p/client.c index b554f8357f96..a2b4a965a5a9 100644 --- a/net/9p/client.c +++ b/net/9p/client.c @@ -685,6 +685,9 @@ p9_client_rpc(struct p9_client *c, int8_t type, const char *fmt, ...) if (IS_ERR(req)) return req; + req->tc.zc = false; + req->rc.zc = false; + if (signal_pending(current)) { sigpending = 1; clear_thread_flag(TIF_SIGPENDING); @@ -783,6 +786,9 @@ static struct p9_req_t *p9_client_zc_rpc(struct p9_client *c, int8_t type, if (IS_ERR(req)) return req; + req->tc.zc = true; + req->rc.zc = true; + if (signal_pending(current)) { sigpending = 1; clear_thread_flag(TIF_SIGPENDING); -- cgit v1.2.3 From a31b3cffbd8e5d032dcb267bf94ee48d71c1a28b Mon Sep 17 00:00:00 2001 From: Christian Schoenebeck Date: Tue, 22 Nov 2022 20:20:29 +0100 Subject: net/9p: fix response size check in p9_check_errors() Since commit 60ece0833b6c ("net/9p: allocate appropriate reduced message buffers") it is no longer appropriate to check server's response size against msize. Check against the previously allocated buffer capacity instead. - Omit this size check entirely for zero-copy messages, as those always allocate 4k (P9_ZC_HDR_SZ) linear buffers which are not used for actual payload and can be much bigger than 4k. - Replace p9_debug() by pr_err() to make sure this message is always printed in case this error is triggered. - Add 9p message type to error message to ease investigation. Link: https://lkml.kernel.org/r/e0edec84b1c80119ae937ce854b4f5f6dbe2d08c.1669144861.git.linux_oss@crudebyte.com Signed-off-by: Christian Schoenebeck Tested-by: Stefano Stabellini Reported-by: kernel test robot Signed-off-by: Dominique Martinet --- net/9p/client.c | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/net/9p/client.c b/net/9p/client.c index a2b4a965a5a9..7b2a997662d9 100644 --- a/net/9p/client.c +++ b/net/9p/client.c @@ -519,10 +519,9 @@ static int p9_check_errors(struct p9_client *c, struct p9_req_t *req) int ecode; err = p9_parse_header(&req->rc, NULL, &type, NULL, 0); - if (req->rc.size >= c->msize) { - p9_debug(P9_DEBUG_ERROR, - "requested packet size too big: %d\n", - req->rc.size); + if (req->rc.size > req->rc.capacity && !req->rc.zc) { + pr_err("requested packet size too big: %d does not fit %zu (type=%d)\n", + req->rc.size, req->rc.capacity, req->rc.id); return -EIO; } /* dump the response from server -- cgit v1.2.3 From 1a4f69ef15ec29b213e2b086b2502644e8ef76ee Mon Sep 17 00:00:00 2001 From: Dominique Martinet Date: Mon, 5 Dec 2022 21:39:01 +0900 Subject: 9p/client: fix data race on req->status KCSAN reported a race between writing req->status in p9_client_cb and accessing it in p9_client_rpc's wait_event. Accesses to req itself is protected by the data barrier (writing req fields, write barrier, writing status // reading status, read barrier, reading other req fields), but status accesses themselves apparently also must be annotated properly with WRITE_ONCE/READ_ONCE when we access it without locks. Follows: - error paths writing status in various threads all can notify p9_client_rpc, so these all also need WRITE_ONCE - there's a similar read loop in trans_virtio for zc case that also needs READ_ONCE - other reads in trans_fd should be protected by the trans_fd lock and lists state machine, as corresponding writers all are within trans_fd and should be under the same lock. If KCSAN complains on them we likely will have something else to fix as well, so it's better to leave them unmarked and look again if required. Link: https://lkml.kernel.org/r/20221205124756.426350-1-asmadeus@codewreck.org Reported-by: Naresh Kamboju Suggested-by: Marco Elver Acked-by: Marco Elver Reviewed-by: Christian Schoenebeck Signed-off-by: Dominique Martinet --- net/9p/client.c | 15 ++++++++------- net/9p/trans_fd.c | 12 ++++++------ net/9p/trans_rdma.c | 4 ++-- net/9p/trans_virtio.c | 9 +++++---- net/9p/trans_xen.c | 4 ++-- 5 files changed, 23 insertions(+), 21 deletions(-) diff --git a/net/9p/client.c b/net/9p/client.c index 7b2a997662d9..fef6516a0639 100644 --- a/net/9p/client.c +++ b/net/9p/client.c @@ -443,7 +443,7 @@ void p9_client_cb(struct p9_client *c, struct p9_req_t *req, int status) * the status change is visible to another thread */ smp_wmb(); - req->status = status; + WRITE_ONCE(req->status, status); wake_up(&req->wq); p9_debug(P9_DEBUG_MUX, "wakeup: %d\n", req->tc.tag); @@ -604,7 +604,7 @@ static int p9_client_flush(struct p9_client *c, struct p9_req_t *oldreq) /* if we haven't received a response for oldreq, * remove it from the list */ - if (oldreq->status == REQ_STATUS_SENT) { + if (READ_ONCE(oldreq->status) == REQ_STATUS_SENT) { if (c->trans_mod->cancelled) c->trans_mod->cancelled(c, oldreq); } @@ -704,7 +704,8 @@ p9_client_rpc(struct p9_client *c, int8_t type, const char *fmt, ...) } again: /* Wait for the response */ - err = wait_event_killable(req->wq, req->status >= REQ_STATUS_RCVD); + err = wait_event_killable(req->wq, + READ_ONCE(req->status) >= REQ_STATUS_RCVD); /* Make sure our req is coherent with regard to updates in other * threads - echoes to wmb() in the callback @@ -718,7 +719,7 @@ again: goto again; } - if (req->status == REQ_STATUS_ERROR) { + if (READ_ONCE(req->status) == REQ_STATUS_ERROR) { p9_debug(P9_DEBUG_ERROR, "req_status error %d\n", req->t_err); err = req->t_err; } @@ -731,7 +732,7 @@ again: p9_client_flush(c, req); /* if we received the response anyway, don't signal error */ - if (req->status == REQ_STATUS_RCVD) + if (READ_ONCE(req->status) == REQ_STATUS_RCVD) err = 0; } recalc_sigpending: @@ -803,7 +804,7 @@ static struct p9_req_t *p9_client_zc_rpc(struct p9_client *c, int8_t type, if (err != -ERESTARTSYS) goto recalc_sigpending; } - if (req->status == REQ_STATUS_ERROR) { + if (READ_ONCE(req->status) == REQ_STATUS_ERROR) { p9_debug(P9_DEBUG_ERROR, "req_status error %d\n", req->t_err); err = req->t_err; } @@ -816,7 +817,7 @@ static struct p9_req_t *p9_client_zc_rpc(struct p9_client *c, int8_t type, p9_client_flush(c, req); /* if we received the response anyway, don't signal error */ - if (req->status == REQ_STATUS_RCVD) + if (READ_ONCE(req->status) == REQ_STATUS_RCVD) err = 0; } recalc_sigpending: diff --git a/net/9p/trans_fd.c b/net/9p/trans_fd.c index 06ec9f7d3318..f8899745571c 100644 --- a/net/9p/trans_fd.c +++ b/net/9p/trans_fd.c @@ -201,11 +201,11 @@ static void p9_conn_cancel(struct p9_conn *m, int err) list_for_each_entry_safe(req, rtmp, &m->req_list, req_list) { list_move(&req->req_list, &cancel_list); - req->status = REQ_STATUS_ERROR; + WRITE_ONCE(req->status, REQ_STATUS_ERROR); } list_for_each_entry_safe(req, rtmp, &m->unsent_req_list, req_list) { list_move(&req->req_list, &cancel_list); - req->status = REQ_STATUS_ERROR; + WRITE_ONCE(req->status, REQ_STATUS_ERROR); } spin_unlock(&m->req_lock); @@ -466,7 +466,7 @@ static void p9_write_work(struct work_struct *work) req = list_entry(m->unsent_req_list.next, struct p9_req_t, req_list); - req->status = REQ_STATUS_SENT; + WRITE_ONCE(req->status, REQ_STATUS_SENT); p9_debug(P9_DEBUG_TRANS, "move req %p\n", req); list_move_tail(&req->req_list, &m->req_list); @@ -675,7 +675,7 @@ static int p9_fd_request(struct p9_client *client, struct p9_req_t *req) return m->err; spin_lock(&m->req_lock); - req->status = REQ_STATUS_UNSENT; + WRITE_ONCE(req->status, REQ_STATUS_UNSENT); list_add_tail(&req->req_list, &m->unsent_req_list); spin_unlock(&m->req_lock); @@ -702,7 +702,7 @@ static int p9_fd_cancel(struct p9_client *client, struct p9_req_t *req) if (req->status == REQ_STATUS_UNSENT) { list_del(&req->req_list); - req->status = REQ_STATUS_FLSHD; + WRITE_ONCE(req->status, REQ_STATUS_FLSHD); p9_req_put(client, req); ret = 0; } @@ -731,7 +731,7 @@ static int p9_fd_cancelled(struct p9_client *client, struct p9_req_t *req) * remove it from the list. */ list_del(&req->req_list); - req->status = REQ_STATUS_FLSHD; + WRITE_ONCE(req->status, REQ_STATUS_FLSHD); spin_unlock(&m->req_lock); p9_req_put(client, req); diff --git a/net/9p/trans_rdma.c b/net/9p/trans_rdma.c index 33a9ac6f2d55..83f9100d46bf 100644 --- a/net/9p/trans_rdma.c +++ b/net/9p/trans_rdma.c @@ -506,7 +506,7 @@ dont_need_post_recv: * because doing if after could erase the REQ_STATUS_RCVD * status in case of a very fast reply. */ - req->status = REQ_STATUS_SENT; + WRITE_ONCE(req->status, REQ_STATUS_SENT); err = ib_post_send(rdma->qp, &wr, NULL); if (err) goto send_error; @@ -516,7 +516,7 @@ dont_need_post_recv: /* Handle errors that happened during or while preparing the send: */ send_error: - req->status = REQ_STATUS_ERROR; + WRITE_ONCE(req->status, REQ_STATUS_ERROR); kfree(c); p9_debug(P9_DEBUG_ERROR, "Error %d in rdma_request()\n", err); diff --git a/net/9p/trans_virtio.c b/net/9p/trans_virtio.c index 19bccfa0d593..3c27ffb781e3 100644 --- a/net/9p/trans_virtio.c +++ b/net/9p/trans_virtio.c @@ -262,7 +262,7 @@ p9_virtio_request(struct p9_client *client, struct p9_req_t *req) p9_debug(P9_DEBUG_TRANS, "9p debug: virtio request\n"); - req->status = REQ_STATUS_SENT; + WRITE_ONCE(req->status, REQ_STATUS_SENT); req_retry: spin_lock_irqsave(&chan->lock, flags); @@ -468,7 +468,7 @@ p9_virtio_zc_request(struct p9_client *client, struct p9_req_t *req, inlen = n; } } - req->status = REQ_STATUS_SENT; + WRITE_ONCE(req->status, REQ_STATUS_SENT); req_retry_pinned: spin_lock_irqsave(&chan->lock, flags); @@ -531,9 +531,10 @@ req_retry_pinned: spin_unlock_irqrestore(&chan->lock, flags); kicked = 1; p9_debug(P9_DEBUG_TRANS, "virtio request kicked\n"); - err = wait_event_killable(req->wq, req->status >= REQ_STATUS_RCVD); + err = wait_event_killable(req->wq, + READ_ONCE(req->status) >= REQ_STATUS_RCVD); // RERROR needs reply (== error string) in static data - if (req->status == REQ_STATUS_RCVD && + if (READ_ONCE(req->status) == REQ_STATUS_RCVD && unlikely(req->rc.sdata[4] == P9_RERROR)) handle_rerror(req, in_hdr_len, offs, in_pages); diff --git a/net/9p/trans_xen.c b/net/9p/trans_xen.c index de2d2ca8819a..9630b1275557 100644 --- a/net/9p/trans_xen.c +++ b/net/9p/trans_xen.c @@ -157,7 +157,7 @@ again: &masked_prod, masked_cons, XEN_9PFS_RING_SIZE(ring)); - p9_req->status = REQ_STATUS_SENT; + WRITE_ONCE(p9_req->status, REQ_STATUS_SENT); virt_wmb(); /* write ring before updating pointer */ prod += size; ring->intf->out_prod = prod; @@ -212,7 +212,7 @@ static void p9_xen_response(struct work_struct *work) dev_warn(&priv->dev->dev, "requested packet size too big: %d for tag %d with capacity %zd\n", h.size, h.tag, req->rc.capacity); - req->status = REQ_STATUS_ERROR; + WRITE_ONCE(req->status, REQ_STATUS_ERROR); goto recv_error; } -- cgit v1.2.3