]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/commitdiff
fixes for 4.19
authorSasha Levin <sashal@kernel.org>
Thu, 27 Jun 2019 23:11:58 +0000 (19:11 -0400)
committerSasha Levin <sashal@kernel.org>
Thu, 27 Jun 2019 23:11:58 +0000 (19:11 -0400)
Signed-off-by: Sasha Levin <sashal@kernel.org>
16 files changed:
queue-4.19/9p-acl-fix-uninitialized-iattr-access.patch [new file with mode: 0644]
queue-4.19/9p-add-a-per-client-fcall-kmem_cache.patch [new file with mode: 0644]
queue-4.19/9p-add-refcount-to-p9_req_t.patch [new file with mode: 0644]
queue-4.19/9p-embed-fcall-in-req-to-round-down-buffer-allocs.patch [new file with mode: 0644]
queue-4.19/9p-p9dirent_read-check-network-provided-name-length.patch [new file with mode: 0644]
queue-4.19/9p-potential-null-dereference.patch [new file with mode: 0644]
queue-4.19/9p-rdma-do-not-disconnect-on-down_interruptible-eaga.patch [new file with mode: 0644]
queue-4.19/9p-rdma-remove-useless-check-in-cm_event_handler.patch [new file with mode: 0644]
queue-4.19/9p-rename-p9_free_req-function.patch [new file with mode: 0644]
queue-4.19/9p-rename-req-to-rreq-in-trans_fd.patch [new file with mode: 0644]
queue-4.19/9p-trans_fd-abort-p9_read_work-if-req-status-changed.patch [new file with mode: 0644]
queue-4.19/9p-trans_fd-put-worker-reqs-on-destroy.patch [new file with mode: 0644]
queue-4.19/9p-use-a-slab-for-allocating-requests.patch [new file with mode: 0644]
queue-4.19/9p-xen-fix-check-for-xenbus_read-error-in-front_prob.patch [new file with mode: 0644]
queue-4.19/net-9p-include-trans_common.h-to-fix-missing-prototy.patch [new file with mode: 0644]
queue-4.19/series

diff --git a/queue-4.19/9p-acl-fix-uninitialized-iattr-access.patch b/queue-4.19/9p-acl-fix-uninitialized-iattr-access.patch
new file mode 100644 (file)
index 0000000..4b25936
--- /dev/null
@@ -0,0 +1,35 @@
+From 7e3be23e7a0de68c73fdbea2ca5306cd3903e294 Mon Sep 17 00:00:00 2001
+From: Dominique Martinet <dominique.martinet@cea.fr>
+Date: Sat, 8 Sep 2018 00:10:57 +0900
+Subject: 9p: acl: fix uninitialized iattr access
+
+[ Upstream commit e02a53d92e197706cad1627bd84705d4aa20a145 ]
+
+iattr is passed to v9fs_vfs_setattr_dotl which does send various
+values from iattr over the wire, even if it tells the server to
+only look at iattr.ia_valid fields this could leak some stack data.
+
+Link: http://lkml.kernel.org/r/1536339057-21974-2-git-send-email-asmadeus@codewreck.org
+Addresses-Coverity-ID: 1195601 ("Uninitalized scalar variable")
+Signed-off-by: Dominique Martinet <dominique.martinet@cea.fr>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ fs/9p/acl.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/fs/9p/acl.c b/fs/9p/acl.c
+index 082d227fa56b..6261719f6f2a 100644
+--- a/fs/9p/acl.c
++++ b/fs/9p/acl.c
+@@ -276,7 +276,7 @@ static int v9fs_xattr_set_acl(const struct xattr_handler *handler,
+       switch (handler->flags) {
+       case ACL_TYPE_ACCESS:
+               if (acl) {
+-                      struct iattr iattr;
++                      struct iattr iattr = { 0 };
+                       struct posix_acl *old_acl = acl;
+                       retval = posix_acl_update_mode(inode, &iattr.ia_mode, &acl);
+-- 
+2.20.1
+
diff --git a/queue-4.19/9p-add-a-per-client-fcall-kmem_cache.patch b/queue-4.19/9p-add-a-per-client-fcall-kmem_cache.patch
new file mode 100644 (file)
index 0000000..ddbe80a
--- /dev/null
@@ -0,0 +1,161 @@
+From 88bf06736a8b5c38a831b73166d9bbcd49fd8825 Mon Sep 17 00:00:00 2001
+From: Dominique Martinet <dominique.martinet@cea.fr>
+Date: Mon, 30 Jul 2018 15:14:37 +0900
+Subject: 9p: add a per-client fcall kmem_cache
+
+[ Upstream commit 91a76be37ff89795526c452a6799576b03bec501 ]
+
+Having a specific cache for the fcall allocations helps speed up
+end-to-end latency.
+
+The caches will automatically be merged if there are multiple caches
+of items with the same size so we do not need to try to share a cache
+between different clients of the same size.
+
+Since the msize is negotiated with the server, only allocate the cache
+after that negotiation has happened - previous allocations or
+allocations of different sizes (e.g. zero-copy fcall) are made with
+kmalloc directly.
+
+Some figures on two beefy VMs with Connect-IB (sriov) / trans=rdma,
+with ior running 32 processes in parallel doing small 32 bytes IOs:
+ - no alloc (4.18-rc7 request cache): 65.4k req/s
+ - non-power of two alloc, no patch: 61.6k req/s
+ - power of two alloc, no patch: 62.2k req/s
+ - non-power of two alloc, with patch: 64.7k req/s
+ - power of two alloc, with patch: 65.1k req/s
+
+Link: http://lkml.kernel.org/r/1532943263-24378-2-git-send-email-asmadeus@codewreck.org
+Signed-off-by: Dominique Martinet <dominique.martinet@cea.fr>
+Acked-by: Jun Piao <piaojun@huawei.com>
+Cc: Matthew Wilcox <willy@infradead.org>
+Cc: Greg Kurz <groug@kaod.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ include/net/9p/9p.h     |  4 ++++
+ include/net/9p/client.h |  1 +
+ net/9p/client.c         | 37 ++++++++++++++++++++++++++++++++-----
+ 3 files changed, 37 insertions(+), 5 deletions(-)
+
+diff --git a/include/net/9p/9p.h b/include/net/9p/9p.h
+index b8eb51a661e5..4ab293f574e0 100644
+--- a/include/net/9p/9p.h
++++ b/include/net/9p/9p.h
+@@ -336,6 +336,9 @@ enum p9_qid_t {
+ #define P9_NOFID      (u32)(~0)
+ #define P9_MAXWELEM   16
++/* Minimal header size: size[4] type[1] tag[2] */
++#define P9_HDRSZ      7
++
+ /* ample room for Twrite/Rread header */
+ #define P9_IOHDRSZ    24
+@@ -558,6 +561,7 @@ struct p9_fcall {
+       size_t offset;
+       size_t capacity;
++      struct kmem_cache *cache;
+       u8 *sdata;
+ };
+diff --git a/include/net/9p/client.h b/include/net/9p/client.h
+index c2671d40bb6b..735f3979d559 100644
+--- a/include/net/9p/client.h
++++ b/include/net/9p/client.h
+@@ -123,6 +123,7 @@ struct p9_client {
+       struct p9_trans_module *trans_mod;
+       enum p9_trans_status status;
+       void *trans;
++      struct kmem_cache *fcall_cache;
+       union {
+               struct {
+diff --git a/net/9p/client.c b/net/9p/client.c
+index 83e39fef58e1..7ef54719c6f7 100644
+--- a/net/9p/client.c
++++ b/net/9p/client.c
+@@ -237,9 +237,16 @@ static int parse_opts(char *opts, struct p9_client *clnt)
+       return ret;
+ }
+-static int p9_fcall_init(struct p9_fcall *fc, int alloc_msize)
++static int p9_fcall_init(struct p9_client *c, struct p9_fcall *fc,
++                       int alloc_msize)
+ {
+-      fc->sdata = kmalloc(alloc_msize, GFP_NOFS);
++      if (likely(c->fcall_cache) && alloc_msize == c->msize) {
++              fc->sdata = kmem_cache_alloc(c->fcall_cache, GFP_NOFS);
++              fc->cache = c->fcall_cache;
++      } else {
++              fc->sdata = kmalloc(alloc_msize, GFP_NOFS);
++              fc->cache = NULL;
++      }
+       if (!fc->sdata)
+               return -ENOMEM;
+       fc->capacity = alloc_msize;
+@@ -248,7 +255,16 @@ static int p9_fcall_init(struct p9_fcall *fc, int alloc_msize)
+ void p9_fcall_fini(struct p9_fcall *fc)
+ {
+-      kfree(fc->sdata);
++      /* sdata can be NULL for interrupted requests in trans_rdma,
++       * and kmem_cache_free does not do NULL-check for us
++       */
++      if (unlikely(!fc->sdata))
++              return;
++
++      if (fc->cache)
++              kmem_cache_free(fc->cache, fc->sdata);
++      else
++              kfree(fc->sdata);
+ }
+ EXPORT_SYMBOL(p9_fcall_fini);
+@@ -273,9 +289,9 @@ p9_tag_alloc(struct p9_client *c, int8_t type, unsigned int max_size)
+       if (!req)
+               return NULL;
+-      if (p9_fcall_init(&req->tc, alloc_msize))
++      if (p9_fcall_init(c, &req->tc, alloc_msize))
+               goto free_req;
+-      if (p9_fcall_init(&req->rc, alloc_msize))
++      if (p9_fcall_init(c, &req->rc, alloc_msize))
+               goto free;
+       p9pdu_reset(&req->tc);
+@@ -965,6 +981,7 @@ struct p9_client *p9_client_create(const char *dev_name, char *options)
+       clnt->trans_mod = NULL;
+       clnt->trans = NULL;
++      clnt->fcall_cache = NULL;
+       client_id = utsname()->nodename;
+       memcpy(clnt->name, client_id, strlen(client_id) + 1);
+@@ -1008,6 +1025,15 @@ struct p9_client *p9_client_create(const char *dev_name, char *options)
+       if (err)
+               goto close_trans;
++      /* P9_HDRSZ + 4 is the smallest packet header we can have that is
++       * followed by data accessed from userspace by read
++       */
++      clnt->fcall_cache =
++              kmem_cache_create_usercopy("9p-fcall-cache", clnt->msize,
++                                         0, 0, P9_HDRSZ + 4,
++                                         clnt->msize - (P9_HDRSZ + 4),
++                                         NULL);
++
+       return clnt;
+ close_trans:
+@@ -1039,6 +1065,7 @@ void p9_client_destroy(struct p9_client *clnt)
+       p9_tag_cleanup(clnt);
++      kmem_cache_destroy(clnt->fcall_cache);
+       kfree(clnt);
+ }
+ EXPORT_SYMBOL(p9_client_destroy);
+-- 
+2.20.1
+
diff --git a/queue-4.19/9p-add-refcount-to-p9_req_t.patch b/queue-4.19/9p-add-refcount-to-p9_req_t.patch
new file mode 100644 (file)
index 0000000..7b3e4dc
--- /dev/null
@@ -0,0 +1,373 @@
+From 407b1adf790f60daa865ecf8cc216e0c31fcce5d Mon Sep 17 00:00:00 2001
+From: Tomas Bortoli <tomasbortoli@gmail.com>
+Date: Tue, 14 Aug 2018 19:43:42 +0200
+Subject: 9p: Add refcount to p9_req_t
+
+[ Upstream commit 728356dedeff8ef999cb436c71333ef4ac51a81c ]
+
+To avoid use-after-free(s), use a refcount to keep track of the
+usable references to any instantiated struct p9_req_t.
+
+This commit adds p9_req_put(), p9_req_get() and p9_req_try_get() as
+wrappers to kref_put(), kref_get() and kref_get_unless_zero().
+These are used by the client and the transports to keep track of
+valid requests' references.
+
+p9_free_req() is added back and used as callback by kref_put().
+
+Add SLAB_TYPESAFE_BY_RCU as it ensures that the memory freed by
+kmem_cache_free() will not be reused for another type until the rcu
+synchronisation period is over, so an address gotten under rcu read
+lock is safe to inc_ref() without corrupting random memory while
+the lock is held.
+
+Link: http://lkml.kernel.org/r/1535626341-20693-1-git-send-email-asmadeus@codewreck.org
+Co-developed-by: Dominique Martinet <dominique.martinet@cea.fr>
+Signed-off-by: Tomas Bortoli <tomasbortoli@gmail.com>
+Reported-by: syzbot+467050c1ce275af2a5b8@syzkaller.appspotmail.com
+Signed-off-by: Dominique Martinet <dominique.martinet@cea.fr>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ include/net/9p/client.h | 14 ++++++++++
+ net/9p/client.c         | 57 ++++++++++++++++++++++++++++++++++++-----
+ net/9p/trans_fd.c       | 11 +++++++-
+ net/9p/trans_rdma.c     |  1 +
+ net/9p/trans_virtio.c   | 26 ++++++++++++++++---
+ net/9p/trans_xen.c      |  1 +
+ 6 files changed, 98 insertions(+), 12 deletions(-)
+
+diff --git a/include/net/9p/client.h b/include/net/9p/client.h
+index 735f3979d559..947a570307a6 100644
+--- a/include/net/9p/client.h
++++ b/include/net/9p/client.h
+@@ -94,6 +94,7 @@ enum p9_req_status_t {
+ struct p9_req_t {
+       int status;
+       int t_err;
++      struct kref refcount;
+       wait_queue_head_t wq;
+       struct p9_fcall tc;
+       struct p9_fcall rc;
+@@ -233,6 +234,19 @@ int p9_client_lock_dotl(struct p9_fid *fid, struct p9_flock *flock, u8 *status);
+ int p9_client_getlock_dotl(struct p9_fid *fid, struct p9_getlock *fl);
+ void p9_fcall_fini(struct p9_fcall *fc);
+ struct p9_req_t *p9_tag_lookup(struct p9_client *, u16);
++
++static inline void p9_req_get(struct p9_req_t *r)
++{
++      kref_get(&r->refcount);
++}
++
++static inline int p9_req_try_get(struct p9_req_t *r)
++{
++      return kref_get_unless_zero(&r->refcount);
++}
++
++int p9_req_put(struct p9_req_t *r);
++
+ void p9_client_cb(struct p9_client *c, struct p9_req_t *req, int status);
+ int p9_parse_header(struct p9_fcall *, int32_t *, int8_t *, int16_t *, int);
+diff --git a/net/9p/client.c b/net/9p/client.c
+index 3cde9f619980..4becde979462 100644
+--- a/net/9p/client.c
++++ b/net/9p/client.c
+@@ -313,6 +313,18 @@ p9_tag_alloc(struct p9_client *c, int8_t type, unsigned int max_size)
+       if (tag < 0)
+               goto free;
++      /* Init ref to two because in the general case there is one ref
++       * that is put asynchronously by a writer thread, one ref
++       * temporarily given by p9_tag_lookup and put by p9_client_cb
++       * in the recv thread, and one ref put by p9_tag_remove in the
++       * main thread. The only exception is virtio that does not use
++       * p9_tag_lookup but does not have a writer thread either
++       * (the write happens synchronously in the request/zc_request
++       * callback), so p9_client_cb eats the second ref there
++       * as the pointer is duplicated directly by virtqueue_add_sgs()
++       */
++      refcount_set(&req->refcount.refcount, 2);
++
+       return req;
+ free:
+@@ -336,10 +348,21 @@ struct p9_req_t *p9_tag_lookup(struct p9_client *c, u16 tag)
+       struct p9_req_t *req;
+       rcu_read_lock();
++again:
+       req = idr_find(&c->reqs, tag);
+-      /* There's no refcount on the req; a malicious server could cause
+-       * us to dereference a NULL pointer
+-       */
++      if (req) {
++              /* We have to be careful with the req found under rcu_read_lock
++               * Thanks to SLAB_TYPESAFE_BY_RCU we can safely try to get the
++               * ref again without corrupting other data, then check again
++               * that the tag matches once we have the ref
++               */
++              if (!p9_req_try_get(req))
++                      goto again;
++              if (req->tc.tag != tag) {
++                      p9_req_put(req);
++                      goto again;
++              }
++      }
+       rcu_read_unlock();
+       return req;
+@@ -353,7 +376,7 @@ EXPORT_SYMBOL(p9_tag_lookup);
+  *
+  * Context: Any context.
+  */
+-static void p9_tag_remove(struct p9_client *c, struct p9_req_t *r)
++static int p9_tag_remove(struct p9_client *c, struct p9_req_t *r)
+ {
+       unsigned long flags;
+       u16 tag = r->tc.tag;
+@@ -362,11 +385,23 @@ static void p9_tag_remove(struct p9_client *c, struct p9_req_t *r)
+       spin_lock_irqsave(&c->lock, flags);
+       idr_remove(&c->reqs, tag);
+       spin_unlock_irqrestore(&c->lock, flags);
++      return p9_req_put(r);
++}
++
++static void p9_req_free(struct kref *ref)
++{
++      struct p9_req_t *r = container_of(ref, struct p9_req_t, refcount);
+       p9_fcall_fini(&r->tc);
+       p9_fcall_fini(&r->rc);
+       kmem_cache_free(p9_req_cache, r);
+ }
++int p9_req_put(struct p9_req_t *r)
++{
++      return kref_put(&r->refcount, p9_req_free);
++}
++EXPORT_SYMBOL(p9_req_put);
++
+ /**
+  * p9_tag_cleanup - cleans up tags structure and reclaims resources
+  * @c:  v9fs client struct
+@@ -382,7 +417,9 @@ static void p9_tag_cleanup(struct p9_client *c)
+       rcu_read_lock();
+       idr_for_each_entry(&c->reqs, req, id) {
+               pr_info("Tag %d still in use\n", id);
+-              p9_tag_remove(c, req);
++              if (p9_tag_remove(c, req) == 0)
++                      pr_warn("Packet with tag %d has still references",
++                              req->tc.tag);
+       }
+       rcu_read_unlock();
+ }
+@@ -406,6 +443,7 @@ void p9_client_cb(struct p9_client *c, struct p9_req_t *req, int status)
+       wake_up(&req->wq);
+       p9_debug(P9_DEBUG_MUX, "wakeup: %d\n", req->tc.tag);
++      p9_req_put(req);
+ }
+ EXPORT_SYMBOL(p9_client_cb);
+@@ -646,9 +684,10 @@ 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 (oldreq->status == REQ_STATUS_SENT) {
+               if (c->trans_mod->cancelled)
+                       c->trans_mod->cancelled(c, oldreq);
++      }
+       p9_tag_remove(c, req);
+       return 0;
+@@ -685,6 +724,8 @@ static struct p9_req_t *p9_client_prepare_req(struct p9_client *c,
+       return req;
+ reterr:
+       p9_tag_remove(c, req);
++      /* We have to put also the 2nd reference as it won't be used */
++      p9_req_put(req);
+       return ERR_PTR(err);
+ }
+@@ -719,6 +760,8 @@ p9_client_rpc(struct p9_client *c, int8_t type, const char *fmt, ...)
+       err = c->trans_mod->request(c, req);
+       if (err < 0) {
++              /* write won't happen */
++              p9_req_put(req);
+               if (err != -ERESTARTSYS && err != -EFAULT)
+                       c->status = Disconnected;
+               goto recalc_sigpending;
+@@ -2259,7 +2302,7 @@ EXPORT_SYMBOL(p9_client_readlink);
+ int __init p9_client_init(void)
+ {
+-      p9_req_cache = KMEM_CACHE(p9_req_t, 0);
++      p9_req_cache = KMEM_CACHE(p9_req_t, SLAB_TYPESAFE_BY_RCU);
+       return p9_req_cache ? 0 : -ENOMEM;
+ }
+diff --git a/net/9p/trans_fd.c b/net/9p/trans_fd.c
+index 51615c0fb744..aca528722183 100644
+--- a/net/9p/trans_fd.c
++++ b/net/9p/trans_fd.c
+@@ -132,6 +132,7 @@ struct p9_conn {
+       struct list_head req_list;
+       struct list_head unsent_req_list;
+       struct p9_req_t *req;
++      struct p9_req_t *wreq;
+       char tmp_buf[7];
+       struct p9_fcall rc;
+       int wpos;
+@@ -383,6 +384,7 @@ static void p9_read_work(struct work_struct *work)
+               m->rc.sdata = NULL;
+               m->rc.offset = 0;
+               m->rc.capacity = 0;
++              p9_req_put(m->req);
+               m->req = NULL;
+       }
+@@ -472,6 +474,8 @@ static void p9_write_work(struct work_struct *work)
+               m->wbuf = req->tc.sdata;
+               m->wsize = req->tc.size;
+               m->wpos = 0;
++              p9_req_get(req);
++              m->wreq = req;
+               spin_unlock(&m->client->lock);
+       }
+@@ -492,8 +496,11 @@ static void p9_write_work(struct work_struct *work)
+       }
+       m->wpos += err;
+-      if (m->wpos == m->wsize)
++      if (m->wpos == m->wsize) {
+               m->wpos = m->wsize = 0;
++              p9_req_put(m->wreq);
++              m->wreq = NULL;
++      }
+ end_clear:
+       clear_bit(Wworksched, &m->wsched);
+@@ -694,6 +701,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;
++              p9_req_put(req);
+               ret = 0;
+       }
+       spin_unlock(&client->lock);
+@@ -711,6 +719,7 @@ static int p9_fd_cancelled(struct p9_client *client, struct p9_req_t *req)
+       spin_lock(&client->lock);
+       list_del(&req->req_list);
+       spin_unlock(&client->lock);
++      p9_req_put(req);
+       return 0;
+ }
+diff --git a/net/9p/trans_rdma.c b/net/9p/trans_rdma.c
+index 5b0cda1aaa7a..9cc9b3a19ee7 100644
+--- a/net/9p/trans_rdma.c
++++ b/net/9p/trans_rdma.c
+@@ -365,6 +365,7 @@ send_done(struct ib_cq *cq, struct ib_wc *wc)
+                           c->busa, c->req->tc.size,
+                           DMA_TO_DEVICE);
+       up(&rdma->sq_sem);
++      p9_req_put(c->req);
+       kfree(c);
+ }
+diff --git a/net/9p/trans_virtio.c b/net/9p/trans_virtio.c
+index 3dd6ce1c0f2d..eb596c2ed546 100644
+--- a/net/9p/trans_virtio.c
++++ b/net/9p/trans_virtio.c
+@@ -207,6 +207,13 @@ static int p9_virtio_cancel(struct p9_client *client, struct p9_req_t *req)
+       return 1;
+ }
++/* Reply won't come, so drop req ref */
++static int p9_virtio_cancelled(struct p9_client *client, struct p9_req_t *req)
++{
++      p9_req_put(req);
++      return 0;
++}
++
+ /**
+  * pack_sg_list_p - Just like pack_sg_list. Instead of taking a buffer,
+  * this takes a list of pages.
+@@ -404,6 +411,7 @@ p9_virtio_zc_request(struct p9_client *client, struct p9_req_t *req,
+       struct scatterlist *sgs[4];
+       size_t offs;
+       int need_drop = 0;
++      int kicked = 0;
+       p9_debug(P9_DEBUG_TRANS, "virtio request\n");
+@@ -411,8 +419,10 @@ p9_virtio_zc_request(struct p9_client *client, struct p9_req_t *req,
+               __le32 sz;
+               int n = p9_get_mapped_pages(chan, &out_pages, uodata,
+                                           outlen, &offs, &need_drop);
+-              if (n < 0)
+-                      return n;
++              if (n < 0) {
++                      err = n;
++                      goto err_out;
++              }
+               out_nr_pages = DIV_ROUND_UP(n + offs, PAGE_SIZE);
+               if (n != outlen) {
+                       __le32 v = cpu_to_le32(n);
+@@ -428,8 +438,10 @@ p9_virtio_zc_request(struct p9_client *client, struct p9_req_t *req,
+       } else if (uidata) {
+               int n = p9_get_mapped_pages(chan, &in_pages, uidata,
+                                           inlen, &offs, &need_drop);
+-              if (n < 0)
+-                      return n;
++              if (n < 0) {
++                      err = n;
++                      goto err_out;
++              }
+               in_nr_pages = DIV_ROUND_UP(n + offs, PAGE_SIZE);
+               if (n != inlen) {
+                       __le32 v = cpu_to_le32(n);
+@@ -498,6 +510,7 @@ p9_virtio_zc_request(struct p9_client *client, struct p9_req_t *req,
+       }
+       virtqueue_kick(chan->vq);
+       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);
+       /*
+@@ -518,6 +531,10 @@ p9_virtio_zc_request(struct p9_client *client, struct p9_req_t *req,
+       }
+       kvfree(in_pages);
+       kvfree(out_pages);
++      if (!kicked) {
++              /* reply won't come */
++              p9_req_put(req);
++      }
+       return err;
+ }
+@@ -750,6 +767,7 @@ static struct p9_trans_module p9_virtio_trans = {
+       .request = p9_virtio_request,
+       .zc_request = p9_virtio_zc_request,
+       .cancel = p9_virtio_cancel,
++      .cancelled = p9_virtio_cancelled,
+       /*
+        * We leave one entry for input and one entry for response
+        * headers. We also skip one more entry to accomodate, address
+diff --git a/net/9p/trans_xen.c b/net/9p/trans_xen.c
+index 782a07f2ad0c..e2fbf3677b9b 100644
+--- a/net/9p/trans_xen.c
++++ b/net/9p/trans_xen.c
+@@ -185,6 +185,7 @@ static int p9_xen_request(struct p9_client *client, struct p9_req_t *p9_req)
+       ring->intf->out_prod = prod;
+       spin_unlock_irqrestore(&ring->lock, flags);
+       notify_remote_via_irq(ring->irq);
++      p9_req_put(p9_req);
+       return 0;
+ }
+-- 
+2.20.1
+
diff --git a/queue-4.19/9p-embed-fcall-in-req-to-round-down-buffer-allocs.patch b/queue-4.19/9p-embed-fcall-in-req-to-round-down-buffer-allocs.patch
new file mode 100644 (file)
index 0000000..4a2f398
--- /dev/null
@@ -0,0 +1,812 @@
+From 900e89fb536b17d1564f9e57aba9620d2a644484 Mon Sep 17 00:00:00 2001
+From: Dominique Martinet <dominique.martinet@cea.fr>
+Date: Mon, 30 Jul 2018 05:55:19 +0000
+Subject: 9p: embed fcall in req to round down buffer allocs
+
+[ Upstream commit 523adb6cc10b48655c0abe556505240741425b49 ]
+
+'msize' is often a power of two, or at least page-aligned, so avoiding
+an overhead of two dozen bytes for each allocation will help the
+allocator do its work and reduce memory fragmentation.
+
+Link: http://lkml.kernel.org/r/1533825236-22896-1-git-send-email-asmadeus@codewreck.org
+Suggested-by: Matthew Wilcox <willy@infradead.org>
+Signed-off-by: Dominique Martinet <dominique.martinet@cea.fr>
+Reviewed-by: Greg Kurz <groug@kaod.org>
+Acked-by: Jun Piao <piaojun@huawei.com>
+Cc: Matthew Wilcox <willy@infradead.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ include/net/9p/client.h |   5 +-
+ net/9p/client.c         | 167 +++++++++++++++++++++-------------------
+ net/9p/trans_fd.c       |  12 +--
+ net/9p/trans_rdma.c     |  29 +++----
+ net/9p/trans_virtio.c   |  18 ++---
+ net/9p/trans_xen.c      |  12 +--
+ 6 files changed, 125 insertions(+), 118 deletions(-)
+
+diff --git a/include/net/9p/client.h b/include/net/9p/client.h
+index a4dc42c53d18..c2671d40bb6b 100644
+--- a/include/net/9p/client.h
++++ b/include/net/9p/client.h
+@@ -95,8 +95,8 @@ struct p9_req_t {
+       int status;
+       int t_err;
+       wait_queue_head_t wq;
+-      struct p9_fcall *tc;
+-      struct p9_fcall *rc;
++      struct p9_fcall tc;
++      struct p9_fcall rc;
+       void *aux;
+       struct list_head req_list;
+ };
+@@ -230,6 +230,7 @@ int p9_client_mkdir_dotl(struct p9_fid *fid, const char *name, int mode,
+                               kgid_t gid, struct p9_qid *);
+ int p9_client_lock_dotl(struct p9_fid *fid, struct p9_flock *flock, u8 *status);
+ int p9_client_getlock_dotl(struct p9_fid *fid, struct p9_getlock *fl);
++void p9_fcall_fini(struct p9_fcall *fc);
+ struct p9_req_t *p9_tag_lookup(struct p9_client *, u16);
+ void p9_client_cb(struct p9_client *c, struct p9_req_t *req, int status);
+diff --git a/net/9p/client.c b/net/9p/client.c
+index d8949c59d46e..83e39fef58e1 100644
+--- a/net/9p/client.c
++++ b/net/9p/client.c
+@@ -237,16 +237,20 @@ static int parse_opts(char *opts, struct p9_client *clnt)
+       return ret;
+ }
+-static struct p9_fcall *p9_fcall_alloc(int alloc_msize)
++static int p9_fcall_init(struct p9_fcall *fc, int alloc_msize)
+ {
+-      struct p9_fcall *fc;
+-      fc = kmalloc(sizeof(struct p9_fcall) + alloc_msize, GFP_NOFS);
+-      if (!fc)
+-              return NULL;
++      fc->sdata = kmalloc(alloc_msize, GFP_NOFS);
++      if (!fc->sdata)
++              return -ENOMEM;
+       fc->capacity = alloc_msize;
+-      fc->sdata = (char *) fc + sizeof(struct p9_fcall);
+-      return fc;
++      return 0;
++}
++
++void p9_fcall_fini(struct p9_fcall *fc)
++{
++      kfree(fc->sdata);
+ }
++EXPORT_SYMBOL(p9_fcall_fini);
+ static struct kmem_cache *p9_req_cache;
+@@ -269,13 +273,13 @@ p9_tag_alloc(struct p9_client *c, int8_t type, unsigned int max_size)
+       if (!req)
+               return NULL;
+-      req->tc = p9_fcall_alloc(alloc_msize);
+-      req->rc = p9_fcall_alloc(alloc_msize);
+-      if (!req->tc || !req->rc)
++      if (p9_fcall_init(&req->tc, alloc_msize))
++              goto free_req;
++      if (p9_fcall_init(&req->rc, alloc_msize))
+               goto free;
+-      p9pdu_reset(req->tc);
+-      p9pdu_reset(req->rc);
++      p9pdu_reset(&req->tc);
++      p9pdu_reset(&req->rc);
+       req->status = REQ_STATUS_ALLOC;
+       init_waitqueue_head(&req->wq);
+       INIT_LIST_HEAD(&req->req_list);
+@@ -287,7 +291,7 @@ p9_tag_alloc(struct p9_client *c, int8_t type, unsigned int max_size)
+                               GFP_NOWAIT);
+       else
+               tag = idr_alloc(&c->reqs, req, 0, P9_NOTAG, GFP_NOWAIT);
+-      req->tc->tag = tag;
++      req->tc.tag = tag;
+       spin_unlock_irq(&c->lock);
+       idr_preload_end();
+       if (tag < 0)
+@@ -296,8 +300,9 @@ p9_tag_alloc(struct p9_client *c, int8_t type, unsigned int max_size)
+       return req;
+ free:
+-      kfree(req->tc);
+-      kfree(req->rc);
++      p9_fcall_fini(&req->tc);
++      p9_fcall_fini(&req->rc);
++free_req:
+       kmem_cache_free(p9_req_cache, req);
+       return ERR_PTR(-ENOMEM);
+ }
+@@ -335,14 +340,14 @@ EXPORT_SYMBOL(p9_tag_lookup);
+ static void p9_free_req(struct p9_client *c, struct p9_req_t *r)
+ {
+       unsigned long flags;
+-      u16 tag = r->tc->tag;
++      u16 tag = r->tc.tag;
+       p9_debug(P9_DEBUG_MUX, "clnt %p req %p tag: %d\n", c, r, tag);
+       spin_lock_irqsave(&c->lock, flags);
+       idr_remove(&c->reqs, tag);
+       spin_unlock_irqrestore(&c->lock, flags);
+-      kfree(r->tc);
+-      kfree(r->rc);
++      p9_fcall_fini(&r->tc);
++      p9_fcall_fini(&r->rc);
+       kmem_cache_free(p9_req_cache, r);
+ }
+@@ -374,7 +379,7 @@ static void p9_tag_cleanup(struct p9_client *c)
+  */
+ void p9_client_cb(struct p9_client *c, struct p9_req_t *req, int status)
+ {
+-      p9_debug(P9_DEBUG_MUX, " tag %d\n", req->tc->tag);
++      p9_debug(P9_DEBUG_MUX, " tag %d\n", req->tc.tag);
+       /*
+        * This barrier is needed to make sure any change made to req before
+@@ -384,7 +389,7 @@ void p9_client_cb(struct p9_client *c, struct p9_req_t *req, int status)
+       req->status = status;
+       wake_up(&req->wq);
+-      p9_debug(P9_DEBUG_MUX, "wakeup: %d\n", req->tc->tag);
++      p9_debug(P9_DEBUG_MUX, "wakeup: %d\n", req->tc.tag);
+ }
+ EXPORT_SYMBOL(p9_client_cb);
+@@ -455,18 +460,18 @@ static int p9_check_errors(struct p9_client *c, struct p9_req_t *req)
+       int err;
+       int ecode;
+-      err = p9_parse_header(req->rc, NULL, &type, NULL, 0);
+-      if (req->rc->size >= c->msize) {
++      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);
++                       req->rc.size);
+               return -EIO;
+       }
+       /*
+        * dump the response from server
+        * This should be after check errors which poplulate pdu_fcall.
+        */
+-      trace_9p_protocol_dump(c, req->rc);
++      trace_9p_protocol_dump(c, &req->rc);
+       if (err) {
+               p9_debug(P9_DEBUG_ERROR, "couldn't parse header %d\n", err);
+               return err;
+@@ -476,7 +481,7 @@ static int p9_check_errors(struct p9_client *c, struct p9_req_t *req)
+       if (!p9_is_proto_dotl(c)) {
+               char *ename;
+-              err = p9pdu_readf(req->rc, c->proto_version, "s?d",
++              err = p9pdu_readf(&req->rc, c->proto_version, "s?d",
+                                 &ename, &ecode);
+               if (err)
+                       goto out_err;
+@@ -492,7 +497,7 @@ static int p9_check_errors(struct p9_client *c, struct p9_req_t *req)
+               }
+               kfree(ename);
+       } else {
+-              err = p9pdu_readf(req->rc, c->proto_version, "d", &ecode);
++              err = p9pdu_readf(&req->rc, c->proto_version, "d", &ecode);
+               err = -ecode;
+               p9_debug(P9_DEBUG_9P, "<<< RLERROR (%d)\n", -ecode);
+@@ -526,12 +531,12 @@ static int p9_check_zc_errors(struct p9_client *c, struct p9_req_t *req,
+       int8_t type;
+       char *ename = NULL;
+-      err = p9_parse_header(req->rc, NULL, &type, NULL, 0);
++      err = p9_parse_header(&req->rc, NULL, &type, NULL, 0);
+       /*
+        * dump the response from server
+        * This should be after parse_header which poplulate pdu_fcall.
+        */
+-      trace_9p_protocol_dump(c, req->rc);
++      trace_9p_protocol_dump(c, &req->rc);
+       if (err) {
+               p9_debug(P9_DEBUG_ERROR, "couldn't parse header %d\n", err);
+               return err;
+@@ -546,13 +551,13 @@ static int p9_check_zc_errors(struct p9_client *c, struct p9_req_t *req,
+               /* 7 = header size for RERROR; */
+               int inline_len = in_hdrlen - 7;
+-              len =  req->rc->size - req->rc->offset;
++              len = req->rc.size - req->rc.offset;
+               if (len > (P9_ZC_HDR_SZ - 7)) {
+                       err = -EFAULT;
+                       goto out_err;
+               }
+-              ename = &req->rc->sdata[req->rc->offset];
++              ename = &req->rc.sdata[req->rc.offset];
+               if (len > inline_len) {
+                       /* We have error in external buffer */
+                       if (!copy_from_iter_full(ename + inline_len,
+@@ -562,7 +567,7 @@ static int p9_check_zc_errors(struct p9_client *c, struct p9_req_t *req,
+                       }
+               }
+               ename = NULL;
+-              err = p9pdu_readf(req->rc, c->proto_version, "s?d",
++              err = p9pdu_readf(&req->rc, c->proto_version, "s?d",
+                                 &ename, &ecode);
+               if (err)
+                       goto out_err;
+@@ -578,7 +583,7 @@ static int p9_check_zc_errors(struct p9_client *c, struct p9_req_t *req,
+               }
+               kfree(ename);
+       } else {
+-              err = p9pdu_readf(req->rc, c->proto_version, "d", &ecode);
++              err = p9pdu_readf(&req->rc, c->proto_version, "d", &ecode);
+               err = -ecode;
+               p9_debug(P9_DEBUG_9P, "<<< RLERROR (%d)\n", -ecode);
+@@ -611,7 +616,7 @@ static int p9_client_flush(struct p9_client *c, struct p9_req_t *oldreq)
+       int16_t oldtag;
+       int err;
+-      err = p9_parse_header(oldreq->tc, NULL, NULL, &oldtag, 1);
++      err = p9_parse_header(&oldreq->tc, NULL, NULL, &oldtag, 1);
+       if (err)
+               return err;
+@@ -655,12 +660,12 @@ static struct p9_req_t *p9_client_prepare_req(struct p9_client *c,
+               return req;
+       /* marshall the data */
+-      p9pdu_prepare(req->tc, req->tc->tag, type);
+-      err = p9pdu_vwritef(req->tc, c->proto_version, fmt, ap);
++      p9pdu_prepare(&req->tc, req->tc.tag, type);
++      err = p9pdu_vwritef(&req->tc, c->proto_version, fmt, ap);
+       if (err)
+               goto reterr;
+-      p9pdu_finalize(c, req->tc);
+-      trace_9p_client_req(c, type, req->tc->tag);
++      p9pdu_finalize(c, &req->tc);
++      trace_9p_client_req(c, type, req->tc.tag);
+       return req;
+ reterr:
+       p9_free_req(c, req);
+@@ -745,7 +750,7 @@ p9_client_rpc(struct p9_client *c, int8_t type, const char *fmt, ...)
+               goto reterr;
+       err = p9_check_errors(c, req);
+-      trace_9p_client_res(c, type, req->rc->tag, err);
++      trace_9p_client_res(c, type, req->rc.tag, err);
+       if (!err)
+               return req;
+ reterr:
+@@ -827,7 +832,7 @@ static struct p9_req_t *p9_client_zc_rpc(struct p9_client *c, int8_t type,
+               goto reterr;
+       err = p9_check_zc_errors(c, req, uidata, in_hdrlen);
+-      trace_9p_client_res(c, type, req->rc->tag, err);
++      trace_9p_client_res(c, type, req->rc.tag, err);
+       if (!err)
+               return req;
+ reterr:
+@@ -910,10 +915,10 @@ static int p9_client_version(struct p9_client *c)
+       if (IS_ERR(req))
+               return PTR_ERR(req);
+-      err = p9pdu_readf(req->rc, c->proto_version, "ds", &msize, &version);
++      err = p9pdu_readf(&req->rc, c->proto_version, "ds", &msize, &version);
+       if (err) {
+               p9_debug(P9_DEBUG_9P, "version error %d\n", err);
+-              trace_9p_protocol_dump(c, req->rc);
++              trace_9p_protocol_dump(c, &req->rc);
+               goto error;
+       }
+@@ -1077,9 +1082,9 @@ struct p9_fid *p9_client_attach(struct p9_client *clnt, struct p9_fid *afid,
+               goto error;
+       }
+-      err = p9pdu_readf(req->rc, clnt->proto_version, "Q", &qid);
++      err = p9pdu_readf(&req->rc, clnt->proto_version, "Q", &qid);
+       if (err) {
+-              trace_9p_protocol_dump(clnt, req->rc);
++              trace_9p_protocol_dump(clnt, &req->rc);
+               p9_free_req(clnt, req);
+               goto error;
+       }
+@@ -1134,9 +1139,9 @@ struct p9_fid *p9_client_walk(struct p9_fid *oldfid, uint16_t nwname,
+               goto error;
+       }
+-      err = p9pdu_readf(req->rc, clnt->proto_version, "R", &nwqids, &wqids);
++      err = p9pdu_readf(&req->rc, clnt->proto_version, "R", &nwqids, &wqids);
+       if (err) {
+-              trace_9p_protocol_dump(clnt, req->rc);
++              trace_9p_protocol_dump(clnt, &req->rc);
+               p9_free_req(clnt, req);
+               goto clunk_fid;
+       }
+@@ -1201,9 +1206,9 @@ int p9_client_open(struct p9_fid *fid, int mode)
+               goto error;
+       }
+-      err = p9pdu_readf(req->rc, clnt->proto_version, "Qd", &qid, &iounit);
++      err = p9pdu_readf(&req->rc, clnt->proto_version, "Qd", &qid, &iounit);
+       if (err) {
+-              trace_9p_protocol_dump(clnt, req->rc);
++              trace_9p_protocol_dump(clnt, &req->rc);
+               goto free_and_error;
+       }
+@@ -1245,9 +1250,9 @@ int p9_client_create_dotl(struct p9_fid *ofid, const char *name, u32 flags, u32
+               goto error;
+       }
+-      err = p9pdu_readf(req->rc, clnt->proto_version, "Qd", qid, &iounit);
++      err = p9pdu_readf(&req->rc, clnt->proto_version, "Qd", qid, &iounit);
+       if (err) {
+-              trace_9p_protocol_dump(clnt, req->rc);
++              trace_9p_protocol_dump(clnt, &req->rc);
+               goto free_and_error;
+       }
+@@ -1290,9 +1295,9 @@ int p9_client_fcreate(struct p9_fid *fid, const char *name, u32 perm, int mode,
+               goto error;
+       }
+-      err = p9pdu_readf(req->rc, clnt->proto_version, "Qd", &qid, &iounit);
++      err = p9pdu_readf(&req->rc, clnt->proto_version, "Qd", &qid, &iounit);
+       if (err) {
+-              trace_9p_protocol_dump(clnt, req->rc);
++              trace_9p_protocol_dump(clnt, &req->rc);
+               goto free_and_error;
+       }
+@@ -1329,9 +1334,9 @@ int p9_client_symlink(struct p9_fid *dfid, const char *name,
+               goto error;
+       }
+-      err = p9pdu_readf(req->rc, clnt->proto_version, "Q", qid);
++      err = p9pdu_readf(&req->rc, clnt->proto_version, "Q", qid);
+       if (err) {
+-              trace_9p_protocol_dump(clnt, req->rc);
++              trace_9p_protocol_dump(clnt, &req->rc);
+               goto free_and_error;
+       }
+@@ -1527,10 +1532,10 @@ p9_client_read(struct p9_fid *fid, u64 offset, struct iov_iter *to, int *err)
+                       break;
+               }
+-              *err = p9pdu_readf(req->rc, clnt->proto_version,
++              *err = p9pdu_readf(&req->rc, clnt->proto_version,
+                                  "D", &count, &dataptr);
+               if (*err) {
+-                      trace_9p_protocol_dump(clnt, req->rc);
++                      trace_9p_protocol_dump(clnt, &req->rc);
+                       p9_free_req(clnt, req);
+                       break;
+               }
+@@ -1600,9 +1605,9 @@ p9_client_write(struct p9_fid *fid, u64 offset, struct iov_iter *from, int *err)
+                       break;
+               }
+-              *err = p9pdu_readf(req->rc, clnt->proto_version, "d", &count);
++              *err = p9pdu_readf(&req->rc, clnt->proto_version, "d", &count);
+               if (*err) {
+-                      trace_9p_protocol_dump(clnt, req->rc);
++                      trace_9p_protocol_dump(clnt, &req->rc);
+                       p9_free_req(clnt, req);
+                       break;
+               }
+@@ -1644,9 +1649,9 @@ struct p9_wstat *p9_client_stat(struct p9_fid *fid)
+               goto error;
+       }
+-      err = p9pdu_readf(req->rc, clnt->proto_version, "wS", &ignored, ret);
++      err = p9pdu_readf(&req->rc, clnt->proto_version, "wS", &ignored, ret);
+       if (err) {
+-              trace_9p_protocol_dump(clnt, req->rc);
++              trace_9p_protocol_dump(clnt, &req->rc);
+               p9_free_req(clnt, req);
+               goto error;
+       }
+@@ -1697,9 +1702,9 @@ struct p9_stat_dotl *p9_client_getattr_dotl(struct p9_fid *fid,
+               goto error;
+       }
+-      err = p9pdu_readf(req->rc, clnt->proto_version, "A", ret);
++      err = p9pdu_readf(&req->rc, clnt->proto_version, "A", ret);
+       if (err) {
+-              trace_9p_protocol_dump(clnt, req->rc);
++              trace_9p_protocol_dump(clnt, &req->rc);
+               p9_free_req(clnt, req);
+               goto error;
+       }
+@@ -1849,11 +1854,11 @@ int p9_client_statfs(struct p9_fid *fid, struct p9_rstatfs *sb)
+               goto error;
+       }
+-      err = p9pdu_readf(req->rc, clnt->proto_version, "ddqqqqqqd", &sb->type,
+-              &sb->bsize, &sb->blocks, &sb->bfree, &sb->bavail,
+-              &sb->files, &sb->ffree, &sb->fsid, &sb->namelen);
++      err = p9pdu_readf(&req->rc, clnt->proto_version, "ddqqqqqqd", &sb->type,
++                        &sb->bsize, &sb->blocks, &sb->bfree, &sb->bavail,
++                        &sb->files, &sb->ffree, &sb->fsid, &sb->namelen);
+       if (err) {
+-              trace_9p_protocol_dump(clnt, req->rc);
++              trace_9p_protocol_dump(clnt, &req->rc);
+               p9_free_req(clnt, req);
+               goto error;
+       }
+@@ -1957,9 +1962,9 @@ struct p9_fid *p9_client_xattrwalk(struct p9_fid *file_fid,
+               err = PTR_ERR(req);
+               goto error;
+       }
+-      err = p9pdu_readf(req->rc, clnt->proto_version, "q", attr_size);
++      err = p9pdu_readf(&req->rc, clnt->proto_version, "q", attr_size);
+       if (err) {
+-              trace_9p_protocol_dump(clnt, req->rc);
++              trace_9p_protocol_dump(clnt, &req->rc);
+               p9_free_req(clnt, req);
+               goto clunk_fid;
+       }
+@@ -2045,9 +2050,9 @@ int p9_client_readdir(struct p9_fid *fid, char *data, u32 count, u64 offset)
+               goto error;
+       }
+-      err = p9pdu_readf(req->rc, clnt->proto_version, "D", &count, &dataptr);
++      err = p9pdu_readf(&req->rc, clnt->proto_version, "D", &count, &dataptr);
+       if (err) {
+-              trace_9p_protocol_dump(clnt, req->rc);
++              trace_9p_protocol_dump(clnt, &req->rc);
+               goto free_and_error;
+       }
+       if (rsize < count) {
+@@ -2086,9 +2091,9 @@ int p9_client_mknod_dotl(struct p9_fid *fid, const char *name, int mode,
+       if (IS_ERR(req))
+               return PTR_ERR(req);
+-      err = p9pdu_readf(req->rc, clnt->proto_version, "Q", qid);
++      err = p9pdu_readf(&req->rc, clnt->proto_version, "Q", qid);
+       if (err) {
+-              trace_9p_protocol_dump(clnt, req->rc);
++              trace_9p_protocol_dump(clnt, &req->rc);
+               goto error;
+       }
+       p9_debug(P9_DEBUG_9P, "<<< RMKNOD qid %x.%llx.%x\n", qid->type,
+@@ -2117,9 +2122,9 @@ int p9_client_mkdir_dotl(struct p9_fid *fid, const char *name, int mode,
+       if (IS_ERR(req))
+               return PTR_ERR(req);
+-      err = p9pdu_readf(req->rc, clnt->proto_version, "Q", qid);
++      err = p9pdu_readf(&req->rc, clnt->proto_version, "Q", qid);
+       if (err) {
+-              trace_9p_protocol_dump(clnt, req->rc);
++              trace_9p_protocol_dump(clnt, &req->rc);
+               goto error;
+       }
+       p9_debug(P9_DEBUG_9P, "<<< RMKDIR qid %x.%llx.%x\n", qid->type,
+@@ -2152,9 +2157,9 @@ int p9_client_lock_dotl(struct p9_fid *fid, struct p9_flock *flock, u8 *status)
+       if (IS_ERR(req))
+               return PTR_ERR(req);
+-      err = p9pdu_readf(req->rc, clnt->proto_version, "b", status);
++      err = p9pdu_readf(&req->rc, clnt->proto_version, "b", status);
+       if (err) {
+-              trace_9p_protocol_dump(clnt, req->rc);
++              trace_9p_protocol_dump(clnt, &req->rc);
+               goto error;
+       }
+       p9_debug(P9_DEBUG_9P, "<<< RLOCK status %i\n", *status);
+@@ -2183,11 +2188,11 @@ int p9_client_getlock_dotl(struct p9_fid *fid, struct p9_getlock *glock)
+       if (IS_ERR(req))
+               return PTR_ERR(req);
+-      err = p9pdu_readf(req->rc, clnt->proto_version, "bqqds", &glock->type,
+-                      &glock->start, &glock->length, &glock->proc_id,
+-                      &glock->client_id);
++      err = p9pdu_readf(&req->rc, clnt->proto_version, "bqqds", &glock->type,
++                        &glock->start, &glock->length, &glock->proc_id,
++                        &glock->client_id);
+       if (err) {
+-              trace_9p_protocol_dump(clnt, req->rc);
++              trace_9p_protocol_dump(clnt, &req->rc);
+               goto error;
+       }
+       p9_debug(P9_DEBUG_9P, "<<< RGETLOCK type %i start %lld length %lld "
+@@ -2213,9 +2218,9 @@ int p9_client_readlink(struct p9_fid *fid, char **target)
+       if (IS_ERR(req))
+               return PTR_ERR(req);
+-      err = p9pdu_readf(req->rc, clnt->proto_version, "s", target);
++      err = p9pdu_readf(&req->rc, clnt->proto_version, "s", target);
+       if (err) {
+-              trace_9p_protocol_dump(clnt, req->rc);
++              trace_9p_protocol_dump(clnt, &req->rc);
+               goto error;
+       }
+       p9_debug(P9_DEBUG_9P, "<<< RREADLINK target %s\n", *target);
+diff --git a/net/9p/trans_fd.c b/net/9p/trans_fd.c
+index e2ef3c782c53..51615c0fb744 100644
+--- a/net/9p/trans_fd.c
++++ b/net/9p/trans_fd.c
+@@ -354,7 +354,7 @@ static void p9_read_work(struct work_struct *work)
+                       goto error;
+               }
+-              if (m->req->rc == NULL) {
++              if (!m->req->rc.sdata) {
+                       p9_debug(P9_DEBUG_ERROR,
+                                "No recv fcall for tag %d (req %p), disconnecting!\n",
+                                m->rc.tag, m->req);
+@@ -362,7 +362,7 @@ static void p9_read_work(struct work_struct *work)
+                       err = -EIO;
+                       goto error;
+               }
+-              m->rc.sdata = (char *)m->req->rc + sizeof(struct p9_fcall);
++              m->rc.sdata = m->req->rc.sdata;
+               memcpy(m->rc.sdata, m->tmp_buf, m->rc.capacity);
+               m->rc.capacity = m->rc.size;
+       }
+@@ -372,7 +372,7 @@ static void p9_read_work(struct work_struct *work)
+        */
+       if ((m->req) && (m->rc.offset == m->rc.capacity)) {
+               p9_debug(P9_DEBUG_TRANS, "got new packet\n");
+-              m->req->rc->size = m->rc.offset;
++              m->req->rc.size = m->rc.offset;
+               spin_lock(&m->client->lock);
+               if (m->req->status != REQ_STATUS_ERROR)
+                       status = REQ_STATUS_RCVD;
+@@ -469,8 +469,8 @@ static void p9_write_work(struct work_struct *work)
+               p9_debug(P9_DEBUG_TRANS, "move req %p\n", req);
+               list_move_tail(&req->req_list, &m->req_list);
+-              m->wbuf = req->tc->sdata;
+-              m->wsize = req->tc->size;
++              m->wbuf = req->tc.sdata;
++              m->wsize = req->tc.size;
+               m->wpos = 0;
+               spin_unlock(&m->client->lock);
+       }
+@@ -663,7 +663,7 @@ static int p9_fd_request(struct p9_client *client, struct p9_req_t *req)
+       struct p9_conn *m = &ts->conn;
+       p9_debug(P9_DEBUG_TRANS, "mux %p task %p tcall %p id %d\n",
+-               m, current, req->tc, req->tc->id);
++               m, current, &req->tc, req->tc.id);
+       if (m->err < 0)
+               return m->err;
+diff --git a/net/9p/trans_rdma.c b/net/9p/trans_rdma.c
+index b513cffeeb3c..5b0cda1aaa7a 100644
+--- a/net/9p/trans_rdma.c
++++ b/net/9p/trans_rdma.c
+@@ -122,7 +122,7 @@ struct p9_rdma_context {
+       dma_addr_t busa;
+       union {
+               struct p9_req_t *req;
+-              struct p9_fcall *rc;
++              struct p9_fcall rc;
+       };
+ };
+@@ -320,8 +320,8 @@ recv_done(struct ib_cq *cq, struct ib_wc *wc)
+       if (wc->status != IB_WC_SUCCESS)
+               goto err_out;
+-      c->rc->size = wc->byte_len;
+-      err = p9_parse_header(c->rc, NULL, NULL, &tag, 1);
++      c->rc.size = wc->byte_len;
++      err = p9_parse_header(&c->rc, NULL, NULL, &tag, 1);
+       if (err)
+               goto err_out;
+@@ -331,12 +331,13 @@ recv_done(struct ib_cq *cq, struct ib_wc *wc)
+       /* Check that we have not yet received a reply for this request.
+        */
+-      if (unlikely(req->rc)) {
++      if (unlikely(req->rc.sdata)) {
+               pr_err("Duplicate reply for request %d", tag);
+               goto err_out;
+       }
+-      req->rc = c->rc;
++      req->rc.size = c->rc.size;
++      req->rc.sdata = c->rc.sdata;
+       p9_client_cb(client, req, REQ_STATUS_RCVD);
+  out:
+@@ -361,7 +362,7 @@ send_done(struct ib_cq *cq, struct ib_wc *wc)
+               container_of(wc->wr_cqe, struct p9_rdma_context, cqe);
+       ib_dma_unmap_single(rdma->cm_id->device,
+-                          c->busa, c->req->tc->size,
++                          c->busa, c->req->tc.size,
+                           DMA_TO_DEVICE);
+       up(&rdma->sq_sem);
+       kfree(c);
+@@ -401,7 +402,7 @@ post_recv(struct p9_client *client, struct p9_rdma_context *c)
+       struct ib_sge sge;
+       c->busa = ib_dma_map_single(rdma->cm_id->device,
+-                                  c->rc->sdata, client->msize,
++                                  c->rc.sdata, client->msize,
+                                   DMA_FROM_DEVICE);
+       if (ib_dma_mapping_error(rdma->cm_id->device, c->busa))
+               goto error;
+@@ -443,9 +444,9 @@ static int rdma_request(struct p9_client *client, struct p9_req_t *req)
+        **/
+       if (unlikely(atomic_read(&rdma->excess_rc) > 0)) {
+               if ((atomic_sub_return(1, &rdma->excess_rc) >= 0)) {
+-                      /* Got one ! */
+-                      kfree(req->rc);
+-                      req->rc = NULL;
++                      /* Got one! */
++                      p9_fcall_fini(&req->rc);
++                      req->rc.sdata = NULL;
+                       goto dont_need_post_recv;
+               } else {
+                       /* We raced and lost. */
+@@ -459,7 +460,7 @@ static int rdma_request(struct p9_client *client, struct p9_req_t *req)
+               err = -ENOMEM;
+               goto recv_error;
+       }
+-      rpl_context->rc = req->rc;
++      rpl_context->rc.sdata = req->rc.sdata;
+       /*
+        * Post a receive buffer for this request. We need to ensure
+@@ -479,7 +480,7 @@ static int rdma_request(struct p9_client *client, struct p9_req_t *req)
+               goto recv_error;
+       }
+       /* remove posted receive buffer from request structure */
+-      req->rc = NULL;
++      req->rc.sdata = NULL;
+ dont_need_post_recv:
+       /* Post the request */
+@@ -491,7 +492,7 @@ static int rdma_request(struct p9_client *client, struct p9_req_t *req)
+       c->req = req;
+       c->busa = ib_dma_map_single(rdma->cm_id->device,
+-                                  c->req->tc->sdata, c->req->tc->size,
++                                  c->req->tc.sdata, c->req->tc.size,
+                                   DMA_TO_DEVICE);
+       if (ib_dma_mapping_error(rdma->cm_id->device, c->busa)) {
+               err = -EIO;
+@@ -501,7 +502,7 @@ static int rdma_request(struct p9_client *client, struct p9_req_t *req)
+       c->cqe.done = send_done;
+       sge.addr = c->busa;
+-      sge.length = c->req->tc->size;
++      sge.length = c->req->tc.size;
+       sge.lkey = rdma->pd->local_dma_lkey;
+       wr.next = NULL;
+diff --git a/net/9p/trans_virtio.c b/net/9p/trans_virtio.c
+index 7728b0acde09..3dd6ce1c0f2d 100644
+--- a/net/9p/trans_virtio.c
++++ b/net/9p/trans_virtio.c
+@@ -155,7 +155,7 @@ static void req_done(struct virtqueue *vq)
+               }
+               if (len) {
+-                      req->rc->size = len;
++                      req->rc.size = len;
+                       p9_client_cb(chan->client, req, REQ_STATUS_RCVD);
+               }
+       }
+@@ -273,12 +273,12 @@ p9_virtio_request(struct p9_client *client, struct p9_req_t *req)
+       out_sgs = in_sgs = 0;
+       /* Handle out VirtIO ring buffers */
+       out = pack_sg_list(chan->sg, 0,
+-                         VIRTQUEUE_NUM, req->tc->sdata, req->tc->size);
++                         VIRTQUEUE_NUM, req->tc.sdata, req->tc.size);
+       if (out)
+               sgs[out_sgs++] = chan->sg;
+       in = pack_sg_list(chan->sg, out,
+-                        VIRTQUEUE_NUM, req->rc->sdata, req->rc->capacity);
++                        VIRTQUEUE_NUM, req->rc.sdata, req->rc.capacity);
+       if (in)
+               sgs[out_sgs + in_sgs++] = chan->sg + out;
+@@ -416,15 +416,15 @@ p9_virtio_zc_request(struct p9_client *client, struct p9_req_t *req,
+               out_nr_pages = DIV_ROUND_UP(n + offs, PAGE_SIZE);
+               if (n != outlen) {
+                       __le32 v = cpu_to_le32(n);
+-                      memcpy(&req->tc->sdata[req->tc->size - 4], &v, 4);
++                      memcpy(&req->tc.sdata[req->tc.size - 4], &v, 4);
+                       outlen = n;
+               }
+               /* The size field of the message must include the length of the
+                * header and the length of the data.  We didn't actually know
+                * the length of the data until this point so add it in now.
+                */
+-              sz = cpu_to_le32(req->tc->size + outlen);
+-              memcpy(&req->tc->sdata[0], &sz, sizeof(sz));
++              sz = cpu_to_le32(req->tc.size + outlen);
++              memcpy(&req->tc.sdata[0], &sz, sizeof(sz));
+       } else if (uidata) {
+               int n = p9_get_mapped_pages(chan, &in_pages, uidata,
+                                           inlen, &offs, &need_drop);
+@@ -433,7 +433,7 @@ p9_virtio_zc_request(struct p9_client *client, struct p9_req_t *req,
+               in_nr_pages = DIV_ROUND_UP(n + offs, PAGE_SIZE);
+               if (n != inlen) {
+                       __le32 v = cpu_to_le32(n);
+-                      memcpy(&req->tc->sdata[req->tc->size - 4], &v, 4);
++                      memcpy(&req->tc.sdata[req->tc.size - 4], &v, 4);
+                       inlen = n;
+               }
+       }
+@@ -445,7 +445,7 @@ p9_virtio_zc_request(struct p9_client *client, struct p9_req_t *req,
+       /* out data */
+       out = pack_sg_list(chan->sg, 0,
+-                         VIRTQUEUE_NUM, req->tc->sdata, req->tc->size);
++                         VIRTQUEUE_NUM, req->tc.sdata, req->tc.size);
+       if (out)
+               sgs[out_sgs++] = chan->sg;
+@@ -464,7 +464,7 @@ p9_virtio_zc_request(struct p9_client *client, struct p9_req_t *req,
+        * alloced memory and payload onto the user buffer.
+        */
+       in = pack_sg_list(chan->sg, out,
+-                        VIRTQUEUE_NUM, req->rc->sdata, in_hdr_len);
++                        VIRTQUEUE_NUM, req->rc.sdata, in_hdr_len);
+       if (in)
+               sgs[out_sgs + in_sgs++] = chan->sg + out;
+diff --git a/net/9p/trans_xen.c b/net/9p/trans_xen.c
+index 843cb823d9b9..782a07f2ad0c 100644
+--- a/net/9p/trans_xen.c
++++ b/net/9p/trans_xen.c
+@@ -141,7 +141,7 @@ static int p9_xen_request(struct p9_client *client, struct p9_req_t *p9_req)
+       struct xen_9pfs_front_priv *priv = NULL;
+       RING_IDX cons, prod, masked_cons, masked_prod;
+       unsigned long flags;
+-      u32 size = p9_req->tc->size;
++      u32 size = p9_req->tc.size;
+       struct xen_9pfs_dataring *ring;
+       int num;
+@@ -154,7 +154,7 @@ static int p9_xen_request(struct p9_client *client, struct p9_req_t *p9_req)
+       if (!priv || priv->client != client)
+               return -EINVAL;
+-      num = p9_req->tc->tag % priv->num_rings;
++      num = p9_req->tc.tag % priv->num_rings;
+       ring = &priv->rings[num];
+ again:
+@@ -176,7 +176,7 @@ static int p9_xen_request(struct p9_client *client, struct p9_req_t *p9_req)
+       masked_prod = xen_9pfs_mask(prod, XEN_9PFS_RING_SIZE);
+       masked_cons = xen_9pfs_mask(cons, XEN_9PFS_RING_SIZE);
+-      xen_9pfs_write_packet(ring->data.out, p9_req->tc->sdata, size,
++      xen_9pfs_write_packet(ring->data.out, p9_req->tc.sdata, size,
+                             &masked_prod, masked_cons, XEN_9PFS_RING_SIZE);
+       p9_req->status = REQ_STATUS_SENT;
+@@ -229,12 +229,12 @@ static void p9_xen_response(struct work_struct *work)
+                       continue;
+               }
+-              memcpy(req->rc, &h, sizeof(h));
+-              req->rc->offset = 0;
++              memcpy(&req->rc, &h, sizeof(h));
++              req->rc.offset = 0;
+               masked_cons = xen_9pfs_mask(cons, XEN_9PFS_RING_SIZE);
+               /* Then, read the whole packet (including the header) */
+-              xen_9pfs_read_packet(req->rc->sdata, ring->data.in, h.size,
++              xen_9pfs_read_packet(req->rc.sdata, ring->data.in, h.size,
+                                    masked_prod, &masked_cons,
+                                    XEN_9PFS_RING_SIZE);
+-- 
+2.20.1
+
diff --git a/queue-4.19/9p-p9dirent_read-check-network-provided-name-length.patch b/queue-4.19/9p-p9dirent_read-check-network-provided-name-length.patch
new file mode 100644 (file)
index 0000000..6445a62
--- /dev/null
@@ -0,0 +1,52 @@
+From e127daee55b27e4dce1403e9b2e2b2323cfece4a Mon Sep 17 00:00:00 2001
+From: Dominique Martinet <dominique.martinet@cea.fr>
+Date: Sat, 8 Sep 2018 00:36:08 +0900
+Subject: 9p: p9dirent_read: check network-provided name length
+
+[ Upstream commit ef5305f1f72eb1cfcda25c382bb0368509c0385b ]
+
+strcpy to dirent->d_name could overflow the buffer, use strscpy to check
+the provided string length and error out if the size was too big.
+
+While we are here, make the function return an error when the pdu
+parsing failed, instead of returning the pdu offset as if it had been a
+success...
+
+Link: http://lkml.kernel.org/r/1536339057-21974-4-git-send-email-asmadeus@codewreck.org
+Addresses-Coverity-ID: 139133 ("Copy into fixed size buffer")
+Signed-off-by: Dominique Martinet <dominique.martinet@cea.fr>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/9p/protocol.c | 12 +++++++++---
+ 1 file changed, 9 insertions(+), 3 deletions(-)
+
+diff --git a/net/9p/protocol.c b/net/9p/protocol.c
+index b4d80c533f89..462ba144cb39 100644
+--- a/net/9p/protocol.c
++++ b/net/9p/protocol.c
+@@ -623,13 +623,19 @@ int p9dirent_read(struct p9_client *clnt, char *buf, int len,
+       if (ret) {
+               p9_debug(P9_DEBUG_9P, "<<< p9dirent_read failed: %d\n", ret);
+               trace_9p_protocol_dump(clnt, &fake_pdu);
+-              goto out;
++              return ret;
+       }
+-      strcpy(dirent->d_name, nameptr);
++      ret = strscpy(dirent->d_name, nameptr, sizeof(dirent->d_name));
++      if (ret < 0) {
++              p9_debug(P9_DEBUG_ERROR,
++                       "On the wire dirent name too long: %s\n",
++                       nameptr);
++              kfree(nameptr);
++              return ret;
++      }
+       kfree(nameptr);
+-out:
+       return fake_pdu.offset;
+ }
+ EXPORT_SYMBOL(p9dirent_read);
+-- 
+2.20.1
+
diff --git a/queue-4.19/9p-potential-null-dereference.patch b/queue-4.19/9p-potential-null-dereference.patch
new file mode 100644 (file)
index 0000000..26dd7fc
--- /dev/null
@@ -0,0 +1,35 @@
+From 1bf47ad7306660e0d0aa4ca0a3f1f96ada81a363 Mon Sep 17 00:00:00 2001
+From: Dan Carpenter <dan.carpenter@oracle.com>
+Date: Wed, 26 Sep 2018 13:39:34 +0300
+Subject: 9p: potential NULL dereference
+
+[ Upstream commit 72ea0321088df2c41eca8cc6160c24bcceb56ac7 ]
+
+p9_tag_alloc() is supposed to return error pointers, but we accidentally
+return a NULL here.  It would cause a NULL dereference in the caller.
+
+Link: http://lkml.kernel.org/m/20180926103934.GA14535@mwanda
+Fixes: 996d5b4db4b1 ("9p: Use a slab for allocating requests")
+Signed-off-by: Dan Carpenter <dan.carpenter@oracle.com>
+Signed-off-by: Dominique Martinet <dominique.martinet@cea.fr>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/9p/client.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/net/9p/client.c b/net/9p/client.c
+index 4becde979462..b615aae5a0f8 100644
+--- a/net/9p/client.c
++++ b/net/9p/client.c
+@@ -287,7 +287,7 @@ p9_tag_alloc(struct p9_client *c, int8_t type, unsigned int max_size)
+       int tag;
+       if (!req)
+-              return NULL;
++              return ERR_PTR(-ENOMEM);
+       if (p9_fcall_init(c, &req->tc, alloc_msize))
+               goto free_req;
+-- 
+2.20.1
+
diff --git a/queue-4.19/9p-rdma-do-not-disconnect-on-down_interruptible-eaga.patch b/queue-4.19/9p-rdma-do-not-disconnect-on-down_interruptible-eaga.patch
new file mode 100644 (file)
index 0000000..6b8598b
--- /dev/null
@@ -0,0 +1,45 @@
+From a4cdf04d2a16298843246f7a7c0dfb650c540d9c Mon Sep 17 00:00:00 2001
+From: Dominique Martinet <dominique.martinet@cea.fr>
+Date: Thu, 30 Aug 2018 19:29:36 +0900
+Subject: 9p/rdma: do not disconnect on down_interruptible EAGAIN
+
+[ Upstream commit 8b894adb2b7e1d1e64b8954569c761eaf3d51ab5 ]
+
+9p/rdma would sometimes drop the connection and display errors in
+recv_done when the user does ^C.
+The errors were caused by recv buffers that were posted at the time
+of disconnect, and we just do not want to disconnect when
+down_interruptible is... interrupted.
+
+Link: http://lkml.kernel.org/r/1535625307-18019-1-git-send-email-asmadeus@codewreck.org
+Signed-off-by: Dominique Martinet <dominique.martinet@cea.fr>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/9p/trans_rdma.c | 4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+diff --git a/net/9p/trans_rdma.c b/net/9p/trans_rdma.c
+index 9cc9b3a19ee7..9719bc4d9424 100644
+--- a/net/9p/trans_rdma.c
++++ b/net/9p/trans_rdma.c
+@@ -477,7 +477,7 @@ static int rdma_request(struct p9_client *client, struct p9_req_t *req)
+       err = post_recv(client, rpl_context);
+       if (err) {
+-              p9_debug(P9_DEBUG_FCALL, "POST RECV failed\n");
++              p9_debug(P9_DEBUG_ERROR, "POST RECV failed: %d\n", err);
+               goto recv_error;
+       }
+       /* remove posted receive buffer from request structure */
+@@ -546,7 +546,7 @@ static int rdma_request(struct p9_client *client, struct p9_req_t *req)
+  recv_error:
+       kfree(rpl_context);
+       spin_lock_irqsave(&rdma->req_lock, flags);
+-      if (rdma->state < P9_RDMA_CLOSING) {
++      if (err != -EINTR && rdma->state < P9_RDMA_CLOSING) {
+               rdma->state = P9_RDMA_CLOSING;
+               spin_unlock_irqrestore(&rdma->req_lock, flags);
+               rdma_disconnect(rdma->cm_id);
+-- 
+2.20.1
+
diff --git a/queue-4.19/9p-rdma-remove-useless-check-in-cm_event_handler.patch b/queue-4.19/9p-rdma-remove-useless-check-in-cm_event_handler.patch
new file mode 100644 (file)
index 0000000..d4f95b5
--- /dev/null
@@ -0,0 +1,36 @@
+From 60bde75379faa65ea117eea23694c41076f51a51 Mon Sep 17 00:00:00 2001
+From: Dominique Martinet <dominique.martinet@cea.fr>
+Date: Sat, 8 Sep 2018 00:26:50 +0900
+Subject: 9p/rdma: remove useless check in cm_event_handler
+
+[ Upstream commit 473c7dd1d7b59ff8f88a5154737e3eac78a96e5b ]
+
+the client c is always dereferenced to get the rdma struct, so c has to
+be a valid pointer at this point.
+Gcc would optimize that away but let's make coverity happy...
+
+Link: http://lkml.kernel.org/r/1536339057-21974-3-git-send-email-asmadeus@codewreck.org
+Addresses-Coverity-ID: 102778 ("Dereference before null check")
+Signed-off-by: Dominique Martinet <dominique.martinet@cea.fr>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/9p/trans_rdma.c | 3 +--
+ 1 file changed, 1 insertion(+), 2 deletions(-)
+
+diff --git a/net/9p/trans_rdma.c b/net/9p/trans_rdma.c
+index 9719bc4d9424..119103bfa82e 100644
+--- a/net/9p/trans_rdma.c
++++ b/net/9p/trans_rdma.c
+@@ -274,8 +274,7 @@ p9_cm_event_handler(struct rdma_cm_id *id, struct rdma_cm_event *event)
+       case RDMA_CM_EVENT_DISCONNECTED:
+               if (rdma)
+                       rdma->state = P9_RDMA_CLOSED;
+-              if (c)
+-                      c->status = Disconnected;
++              c->status = Disconnected;
+               break;
+       case RDMA_CM_EVENT_TIMEWAIT_EXIT:
+-- 
+2.20.1
+
diff --git a/queue-4.19/9p-rename-p9_free_req-function.patch b/queue-4.19/9p-rename-p9_free_req-function.patch
new file mode 100644 (file)
index 0000000..86c6553
--- /dev/null
@@ -0,0 +1,454 @@
+From 88d4d894ebd7dbe5f31e765434cbe08ca0ea46e7 Mon Sep 17 00:00:00 2001
+From: Tomas Bortoli <tomasbortoli@gmail.com>
+Date: Sat, 11 Aug 2018 16:42:53 +0200
+Subject: 9p: rename p9_free_req() function
+
+[ Upstream commit 43cbcbee9938b17f77cf34f1bc12d302f456810f ]
+
+In sight of the next patch to add a refcount in p9_req_t, rename
+the p9_free_req() function in p9_release_req().
+
+In the next patch the actual kfree will be moved to another function.
+
+Link: http://lkml.kernel.org/r/20180811144254.23665-1-tomasbortoli@gmail.com
+Signed-off-by: Tomas Bortoli <tomasbortoli@gmail.com>
+Acked-by: Jun Piao <piaojun@huawei.com>
+Signed-off-by: Dominique Martinet <dominique.martinet@cea.fr>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/9p/client.c | 100 ++++++++++++++++++++++++------------------------
+ 1 file changed, 50 insertions(+), 50 deletions(-)
+
+diff --git a/net/9p/client.c b/net/9p/client.c
+index 7ef54719c6f7..3cde9f619980 100644
+--- a/net/9p/client.c
++++ b/net/9p/client.c
+@@ -347,13 +347,13 @@ struct p9_req_t *p9_tag_lookup(struct p9_client *c, u16 tag)
+ EXPORT_SYMBOL(p9_tag_lookup);
+ /**
+- * p9_free_req - Free a request.
++ * p9_tag_remove - Remove a tag.
+  * @c: Client session.
+- * @r: Request to free.
++ * @r: Request of reference.
+  *
+  * Context: Any context.
+  */
+-static void p9_free_req(struct p9_client *c, struct p9_req_t *r)
++static void p9_tag_remove(struct p9_client *c, struct p9_req_t *r)
+ {
+       unsigned long flags;
+       u16 tag = r->tc.tag;
+@@ -382,7 +382,7 @@ static void p9_tag_cleanup(struct p9_client *c)
+       rcu_read_lock();
+       idr_for_each_entry(&c->reqs, req, id) {
+               pr_info("Tag %d still in use\n", id);
+-              p9_free_req(c, req);
++              p9_tag_remove(c, req);
+       }
+       rcu_read_unlock();
+ }
+@@ -650,7 +650,7 @@ static int p9_client_flush(struct p9_client *c, struct p9_req_t *oldreq)
+               if (c->trans_mod->cancelled)
+                       c->trans_mod->cancelled(c, oldreq);
+-      p9_free_req(c, req);
++      p9_tag_remove(c, req);
+       return 0;
+ }
+@@ -684,7 +684,7 @@ static struct p9_req_t *p9_client_prepare_req(struct p9_client *c,
+       trace_9p_client_req(c, type, req->tc.tag);
+       return req;
+ reterr:
+-      p9_free_req(c, req);
++      p9_tag_remove(c, req);
+       return ERR_PTR(err);
+ }
+@@ -694,7 +694,7 @@ static struct p9_req_t *p9_client_prepare_req(struct p9_client *c,
+  * @type: type of request
+  * @fmt: protocol format string (see protocol.c)
+  *
+- * Returns request structure (which client must free using p9_free_req)
++ * Returns request structure (which client must free using p9_tag_remove)
+  */
+ static struct p9_req_t *
+@@ -770,7 +770,7 @@ p9_client_rpc(struct p9_client *c, int8_t type, const char *fmt, ...)
+       if (!err)
+               return req;
+ reterr:
+-      p9_free_req(c, req);
++      p9_tag_remove(c, req);
+       return ERR_PTR(safe_errno(err));
+ }
+@@ -785,7 +785,7 @@ p9_client_rpc(struct p9_client *c, int8_t type, const char *fmt, ...)
+  * @hdrlen: reader header size, This is the size of response protocol data
+  * @fmt: protocol format string (see protocol.c)
+  *
+- * Returns request structure (which client must free using p9_free_req)
++ * Returns request structure (which client must free using p9_tag_remove)
+  */
+ static struct p9_req_t *p9_client_zc_rpc(struct p9_client *c, int8_t type,
+                                        struct iov_iter *uidata,
+@@ -852,7 +852,7 @@ static struct p9_req_t *p9_client_zc_rpc(struct p9_client *c, int8_t type,
+       if (!err)
+               return req;
+ reterr:
+-      p9_free_req(c, req);
++      p9_tag_remove(c, req);
+       return ERR_PTR(safe_errno(err));
+ }
+@@ -963,7 +963,7 @@ static int p9_client_version(struct p9_client *c)
+ error:
+       kfree(version);
+-      p9_free_req(c, req);
++      p9_tag_remove(c, req);
+       return err;
+ }
+@@ -1112,7 +1112,7 @@ struct p9_fid *p9_client_attach(struct p9_client *clnt, struct p9_fid *afid,
+       err = p9pdu_readf(&req->rc, clnt->proto_version, "Q", &qid);
+       if (err) {
+               trace_9p_protocol_dump(clnt, &req->rc);
+-              p9_free_req(clnt, req);
++              p9_tag_remove(clnt, req);
+               goto error;
+       }
+@@ -1121,7 +1121,7 @@ struct p9_fid *p9_client_attach(struct p9_client *clnt, struct p9_fid *afid,
+       memmove(&fid->qid, &qid, sizeof(struct p9_qid));
+-      p9_free_req(clnt, req);
++      p9_tag_remove(clnt, req);
+       return fid;
+ error:
+@@ -1169,10 +1169,10 @@ struct p9_fid *p9_client_walk(struct p9_fid *oldfid, uint16_t nwname,
+       err = p9pdu_readf(&req->rc, clnt->proto_version, "R", &nwqids, &wqids);
+       if (err) {
+               trace_9p_protocol_dump(clnt, &req->rc);
+-              p9_free_req(clnt, req);
++              p9_tag_remove(clnt, req);
+               goto clunk_fid;
+       }
+-      p9_free_req(clnt, req);
++      p9_tag_remove(clnt, req);
+       p9_debug(P9_DEBUG_9P, "<<< RWALK nwqid %d:\n", nwqids);
+@@ -1247,7 +1247,7 @@ int p9_client_open(struct p9_fid *fid, int mode)
+       fid->iounit = iounit;
+ free_and_error:
+-      p9_free_req(clnt, req);
++      p9_tag_remove(clnt, req);
+ error:
+       return err;
+ }
+@@ -1292,7 +1292,7 @@ int p9_client_create_dotl(struct p9_fid *ofid, const char *name, u32 flags, u32
+       ofid->iounit = iounit;
+ free_and_error:
+-      p9_free_req(clnt, req);
++      p9_tag_remove(clnt, req);
+ error:
+       return err;
+ }
+@@ -1337,7 +1337,7 @@ int p9_client_fcreate(struct p9_fid *fid, const char *name, u32 perm, int mode,
+       fid->iounit = iounit;
+ free_and_error:
+-      p9_free_req(clnt, req);
++      p9_tag_remove(clnt, req);
+ error:
+       return err;
+ }
+@@ -1371,7 +1371,7 @@ int p9_client_symlink(struct p9_fid *dfid, const char *name,
+                       qid->type, (unsigned long long)qid->path, qid->version);
+ free_and_error:
+-      p9_free_req(clnt, req);
++      p9_tag_remove(clnt, req);
+ error:
+       return err;
+ }
+@@ -1391,7 +1391,7 @@ int p9_client_link(struct p9_fid *dfid, struct p9_fid *oldfid, const char *newna
+               return PTR_ERR(req);
+       p9_debug(P9_DEBUG_9P, "<<< RLINK\n");
+-      p9_free_req(clnt, req);
++      p9_tag_remove(clnt, req);
+       return 0;
+ }
+ EXPORT_SYMBOL(p9_client_link);
+@@ -1415,7 +1415,7 @@ int p9_client_fsync(struct p9_fid *fid, int datasync)
+       p9_debug(P9_DEBUG_9P, "<<< RFSYNC fid %d\n", fid->fid);
+-      p9_free_req(clnt, req);
++      p9_tag_remove(clnt, req);
+ error:
+       return err;
+@@ -1450,7 +1450,7 @@ int p9_client_clunk(struct p9_fid *fid)
+       p9_debug(P9_DEBUG_9P, "<<< RCLUNK fid %d\n", fid->fid);
+-      p9_free_req(clnt, req);
++      p9_tag_remove(clnt, req);
+ error:
+       /*
+        * Fid is not valid even after a failed clunk
+@@ -1484,7 +1484,7 @@ int p9_client_remove(struct p9_fid *fid)
+       p9_debug(P9_DEBUG_9P, "<<< RREMOVE fid %d\n", fid->fid);
+-      p9_free_req(clnt, req);
++      p9_tag_remove(clnt, req);
+ error:
+       if (err == -ERESTARTSYS)
+               p9_client_clunk(fid);
+@@ -1511,7 +1511,7 @@ int p9_client_unlinkat(struct p9_fid *dfid, const char *name, int flags)
+       }
+       p9_debug(P9_DEBUG_9P, "<<< RUNLINKAT fid %d %s\n", dfid->fid, name);
+-      p9_free_req(clnt, req);
++      p9_tag_remove(clnt, req);
+ error:
+       return err;
+ }
+@@ -1563,7 +1563,7 @@ p9_client_read(struct p9_fid *fid, u64 offset, struct iov_iter *to, int *err)
+                                  "D", &count, &dataptr);
+               if (*err) {
+                       trace_9p_protocol_dump(clnt, &req->rc);
+-                      p9_free_req(clnt, req);
++                      p9_tag_remove(clnt, req);
+                       break;
+               }
+               if (rsize < count) {
+@@ -1573,7 +1573,7 @@ p9_client_read(struct p9_fid *fid, u64 offset, struct iov_iter *to, int *err)
+               p9_debug(P9_DEBUG_9P, "<<< RREAD count %d\n", count);
+               if (!count) {
+-                      p9_free_req(clnt, req);
++                      p9_tag_remove(clnt, req);
+                       break;
+               }
+@@ -1583,7 +1583,7 @@ p9_client_read(struct p9_fid *fid, u64 offset, struct iov_iter *to, int *err)
+                       offset += n;
+                       if (n != count) {
+                               *err = -EFAULT;
+-                              p9_free_req(clnt, req);
++                              p9_tag_remove(clnt, req);
+                               break;
+                       }
+               } else {
+@@ -1591,7 +1591,7 @@ p9_client_read(struct p9_fid *fid, u64 offset, struct iov_iter *to, int *err)
+                       total += count;
+                       offset += count;
+               }
+-              p9_free_req(clnt, req);
++              p9_tag_remove(clnt, req);
+       }
+       return total;
+ }
+@@ -1635,7 +1635,7 @@ p9_client_write(struct p9_fid *fid, u64 offset, struct iov_iter *from, int *err)
+               *err = p9pdu_readf(&req->rc, clnt->proto_version, "d", &count);
+               if (*err) {
+                       trace_9p_protocol_dump(clnt, &req->rc);
+-                      p9_free_req(clnt, req);
++                      p9_tag_remove(clnt, req);
+                       break;
+               }
+               if (rsize < count) {
+@@ -1645,7 +1645,7 @@ p9_client_write(struct p9_fid *fid, u64 offset, struct iov_iter *from, int *err)
+               p9_debug(P9_DEBUG_9P, "<<< RWRITE count %d\n", count);
+-              p9_free_req(clnt, req);
++              p9_tag_remove(clnt, req);
+               iov_iter_advance(from, count);
+               total += count;
+               offset += count;
+@@ -1679,7 +1679,7 @@ struct p9_wstat *p9_client_stat(struct p9_fid *fid)
+       err = p9pdu_readf(&req->rc, clnt->proto_version, "wS", &ignored, ret);
+       if (err) {
+               trace_9p_protocol_dump(clnt, &req->rc);
+-              p9_free_req(clnt, req);
++              p9_tag_remove(clnt, req);
+               goto error;
+       }
+@@ -1696,7 +1696,7 @@ struct p9_wstat *p9_client_stat(struct p9_fid *fid)
+               from_kgid(&init_user_ns, ret->n_gid),
+               from_kuid(&init_user_ns, ret->n_muid));
+-      p9_free_req(clnt, req);
++      p9_tag_remove(clnt, req);
+       return ret;
+ error:
+@@ -1732,7 +1732,7 @@ struct p9_stat_dotl *p9_client_getattr_dotl(struct p9_fid *fid,
+       err = p9pdu_readf(&req->rc, clnt->proto_version, "A", ret);
+       if (err) {
+               trace_9p_protocol_dump(clnt, &req->rc);
+-              p9_free_req(clnt, req);
++              p9_tag_remove(clnt, req);
+               goto error;
+       }
+@@ -1757,7 +1757,7 @@ struct p9_stat_dotl *p9_client_getattr_dotl(struct p9_fid *fid,
+               ret->st_ctime_nsec, ret->st_btime_sec, ret->st_btime_nsec,
+               ret->st_gen, ret->st_data_version);
+-      p9_free_req(clnt, req);
++      p9_tag_remove(clnt, req);
+       return ret;
+ error:
+@@ -1826,7 +1826,7 @@ int p9_client_wstat(struct p9_fid *fid, struct p9_wstat *wst)
+       p9_debug(P9_DEBUG_9P, "<<< RWSTAT fid %d\n", fid->fid);
+-      p9_free_req(clnt, req);
++      p9_tag_remove(clnt, req);
+ error:
+       return err;
+ }
+@@ -1858,7 +1858,7 @@ int p9_client_setattr(struct p9_fid *fid, struct p9_iattr_dotl *p9attr)
+               goto error;
+       }
+       p9_debug(P9_DEBUG_9P, "<<< RSETATTR fid %d\n", fid->fid);
+-      p9_free_req(clnt, req);
++      p9_tag_remove(clnt, req);
+ error:
+       return err;
+ }
+@@ -1886,7 +1886,7 @@ int p9_client_statfs(struct p9_fid *fid, struct p9_rstatfs *sb)
+                         &sb->files, &sb->ffree, &sb->fsid, &sb->namelen);
+       if (err) {
+               trace_9p_protocol_dump(clnt, &req->rc);
+-              p9_free_req(clnt, req);
++              p9_tag_remove(clnt, req);
+               goto error;
+       }
+@@ -1897,7 +1897,7 @@ int p9_client_statfs(struct p9_fid *fid, struct p9_rstatfs *sb)
+               sb->blocks, sb->bfree, sb->bavail, sb->files,  sb->ffree,
+               sb->fsid, (long int)sb->namelen);
+-      p9_free_req(clnt, req);
++      p9_tag_remove(clnt, req);
+ error:
+       return err;
+ }
+@@ -1925,7 +1925,7 @@ int p9_client_rename(struct p9_fid *fid,
+       p9_debug(P9_DEBUG_9P, "<<< RRENAME fid %d\n", fid->fid);
+-      p9_free_req(clnt, req);
++      p9_tag_remove(clnt, req);
+ error:
+       return err;
+ }
+@@ -1955,7 +1955,7 @@ int p9_client_renameat(struct p9_fid *olddirfid, const char *old_name,
+       p9_debug(P9_DEBUG_9P, "<<< RRENAMEAT newdirfid %d new name %s\n",
+                  newdirfid->fid, new_name);
+-      p9_free_req(clnt, req);
++      p9_tag_remove(clnt, req);
+ error:
+       return err;
+ }
+@@ -1992,10 +1992,10 @@ struct p9_fid *p9_client_xattrwalk(struct p9_fid *file_fid,
+       err = p9pdu_readf(&req->rc, clnt->proto_version, "q", attr_size);
+       if (err) {
+               trace_9p_protocol_dump(clnt, &req->rc);
+-              p9_free_req(clnt, req);
++              p9_tag_remove(clnt, req);
+               goto clunk_fid;
+       }
+-      p9_free_req(clnt, req);
++      p9_tag_remove(clnt, req);
+       p9_debug(P9_DEBUG_9P, "<<<  RXATTRWALK fid %d size %llu\n",
+               attr_fid->fid, *attr_size);
+       return attr_fid;
+@@ -2029,7 +2029,7 @@ int p9_client_xattrcreate(struct p9_fid *fid, const char *name,
+               goto error;
+       }
+       p9_debug(P9_DEBUG_9P, "<<< RXATTRCREATE fid %d\n", fid->fid);
+-      p9_free_req(clnt, req);
++      p9_tag_remove(clnt, req);
+ error:
+       return err;
+ }
+@@ -2092,11 +2092,11 @@ int p9_client_readdir(struct p9_fid *fid, char *data, u32 count, u64 offset)
+       if (non_zc)
+               memmove(data, dataptr, count);
+-      p9_free_req(clnt, req);
++      p9_tag_remove(clnt, req);
+       return count;
+ free_and_error:
+-      p9_free_req(clnt, req);
++      p9_tag_remove(clnt, req);
+ error:
+       return err;
+ }
+@@ -2127,7 +2127,7 @@ int p9_client_mknod_dotl(struct p9_fid *fid, const char *name, int mode,
+                               (unsigned long long)qid->path, qid->version);
+ error:
+-      p9_free_req(clnt, req);
++      p9_tag_remove(clnt, req);
+       return err;
+ }
+@@ -2158,7 +2158,7 @@ int p9_client_mkdir_dotl(struct p9_fid *fid, const char *name, int mode,
+                               (unsigned long long)qid->path, qid->version);
+ error:
+-      p9_free_req(clnt, req);
++      p9_tag_remove(clnt, req);
+       return err;
+ }
+@@ -2191,7 +2191,7 @@ int p9_client_lock_dotl(struct p9_fid *fid, struct p9_flock *flock, u8 *status)
+       }
+       p9_debug(P9_DEBUG_9P, "<<< RLOCK status %i\n", *status);
+ error:
+-      p9_free_req(clnt, req);
++      p9_tag_remove(clnt, req);
+       return err;
+ }
+@@ -2226,7 +2226,7 @@ int p9_client_getlock_dotl(struct p9_fid *fid, struct p9_getlock *glock)
+               "proc_id %d client_id %s\n", glock->type, glock->start,
+               glock->length, glock->proc_id, glock->client_id);
+ error:
+-      p9_free_req(clnt, req);
++      p9_tag_remove(clnt, req);
+       return err;
+ }
+ EXPORT_SYMBOL(p9_client_getlock_dotl);
+@@ -2252,7 +2252,7 @@ int p9_client_readlink(struct p9_fid *fid, char **target)
+       }
+       p9_debug(P9_DEBUG_9P, "<<< RREADLINK target %s\n", *target);
+ error:
+-      p9_free_req(clnt, req);
++      p9_tag_remove(clnt, req);
+       return err;
+ }
+ EXPORT_SYMBOL(p9_client_readlink);
+-- 
+2.20.1
+
diff --git a/queue-4.19/9p-rename-req-to-rreq-in-trans_fd.patch b/queue-4.19/9p-rename-req-to-rreq-in-trans_fd.patch
new file mode 100644 (file)
index 0000000..d8e3d13
--- /dev/null
@@ -0,0 +1,102 @@
+From 02d2b1cb4288e1415904551c8d589cef979258ba Mon Sep 17 00:00:00 2001
+From: Tomas Bortoli <tomasbortoli@gmail.com>
+Date: Mon, 3 Sep 2018 18:03:21 +0200
+Subject: 9p: Rename req to rreq in trans_fd
+
+[ Upstream commit 6d35190f395316916c8bb4aabd35a182890bf856 ]
+
+In struct p9_conn, rename req to rreq as it is used by the read routine.
+
+Link: http://lkml.kernel.org/r/20180903160321.2181-1-tomasbortoli@gmail.com
+Signed-off-by: Tomas Bortoli <tomasbortoli@gmail.com>
+Suggested-by: Jun Piao <piaojun@huawei.com>
+Signed-off-by: Dominique Martinet <dominique.martinet@cea.fr>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/9p/trans_fd.c | 30 +++++++++++++++---------------
+ 1 file changed, 15 insertions(+), 15 deletions(-)
+
+diff --git a/net/9p/trans_fd.c b/net/9p/trans_fd.c
+index aca528722183..12559c474dde 100644
+--- a/net/9p/trans_fd.c
++++ b/net/9p/trans_fd.c
+@@ -131,7 +131,7 @@ struct p9_conn {
+       int err;
+       struct list_head req_list;
+       struct list_head unsent_req_list;
+-      struct p9_req_t *req;
++      struct p9_req_t *rreq;
+       struct p9_req_t *wreq;
+       char tmp_buf[7];
+       struct p9_fcall rc;
+@@ -323,7 +323,7 @@ static void p9_read_work(struct work_struct *work)
+       m->rc.offset += err;
+       /* header read in */
+-      if ((!m->req) && (m->rc.offset == m->rc.capacity)) {
++      if ((!m->rreq) && (m->rc.offset == m->rc.capacity)) {
+               p9_debug(P9_DEBUG_TRANS, "got new header\n");
+               /* Header size */
+@@ -347,23 +347,23 @@ static void p9_read_work(struct work_struct *work)
+                        "mux %p pkt: size: %d bytes tag: %d\n",
+                        m, m->rc.size, m->rc.tag);
+-              m->req = p9_tag_lookup(m->client, m->rc.tag);
+-              if (!m->req || (m->req->status != REQ_STATUS_SENT)) {
++              m->rreq = p9_tag_lookup(m->client, m->rc.tag);
++              if (!m->rreq || (m->rreq->status != REQ_STATUS_SENT)) {
+                       p9_debug(P9_DEBUG_ERROR, "Unexpected packet tag %d\n",
+                                m->rc.tag);
+                       err = -EIO;
+                       goto error;
+               }
+-              if (!m->req->rc.sdata) {
++              if (!m->rreq->rc.sdata) {
+                       p9_debug(P9_DEBUG_ERROR,
+                                "No recv fcall for tag %d (req %p), disconnecting!\n",
+-                               m->rc.tag, m->req);
+-                      m->req = NULL;
++                               m->rc.tag, m->rreq);
++                      m->rreq = NULL;
+                       err = -EIO;
+                       goto error;
+               }
+-              m->rc.sdata = m->req->rc.sdata;
++              m->rc.sdata = m->rreq->rc.sdata;
+               memcpy(m->rc.sdata, m->tmp_buf, m->rc.capacity);
+               m->rc.capacity = m->rc.size;
+       }
+@@ -371,21 +371,21 @@ static void p9_read_work(struct work_struct *work)
+       /* packet is read in
+        * not an else because some packets (like clunk) have no payload
+        */
+-      if ((m->req) && (m->rc.offset == m->rc.capacity)) {
++      if ((m->rreq) && (m->rc.offset == m->rc.capacity)) {
+               p9_debug(P9_DEBUG_TRANS, "got new packet\n");
+-              m->req->rc.size = m->rc.offset;
++              m->rreq->rc.size = m->rc.offset;
+               spin_lock(&m->client->lock);
+-              if (m->req->status != REQ_STATUS_ERROR)
++              if (m->rreq->status != REQ_STATUS_ERROR)
+                       status = REQ_STATUS_RCVD;
+-              list_del(&m->req->req_list);
++              list_del(&m->rreq->req_list);
+               /* update req->status while holding client->lock  */
+-              p9_client_cb(m->client, m->req, status);
++              p9_client_cb(m->client, m->rreq, status);
+               spin_unlock(&m->client->lock);
+               m->rc.sdata = NULL;
+               m->rc.offset = 0;
+               m->rc.capacity = 0;
+-              p9_req_put(m->req);
+-              m->req = NULL;
++              p9_req_put(m->rreq);
++              m->rreq = NULL;
+       }
+ end_clear:
+-- 
+2.20.1
+
diff --git a/queue-4.19/9p-trans_fd-abort-p9_read_work-if-req-status-changed.patch b/queue-4.19/9p-trans_fd-abort-p9_read_work-if-req-status-changed.patch
new file mode 100644 (file)
index 0000000..7114202
--- /dev/null
@@ -0,0 +1,64 @@
+From 7c574af33f301066e6e23624f2f0b42c2763dae9 Mon Sep 17 00:00:00 2001
+From: Dominique Martinet <dominique.martinet@cea.fr>
+Date: Tue, 9 Oct 2018 11:18:52 +0900
+Subject: 9p/trans_fd: abort p9_read_work if req status changed
+
+[ Upstream commit e4ca13f7d075e551dc158df6af18fb412a1dba0a ]
+
+p9_read_work would try to handle an errored req even if it got put to
+error state by another thread between the lookup (that worked) and the
+time it had been fully read.
+The request itself is safe to use because we hold a ref to it from the
+lookup (for m->rreq, so it was safe to read into the request data buffer
+until this point), but the req_list has been deleted at the same time
+status changed, and client_cb already has been called as well, so we
+should not do either.
+
+Link: http://lkml.kernel.org/r/1539057956-23741-1-git-send-email-asmadeus@codewreck.org
+Signed-off-by: Dominique Martinet <dominique.martinet@cea.fr>
+Reported-by: syzbot+2222c34dc40b515f30dc@syzkaller.appspotmail.com
+Cc: Eric Van Hensbergen <ericvh@gmail.com>
+Cc: Latchesar Ionkov <lucho@ionkov.net>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/9p/trans_fd.c | 17 +++++++++++------
+ 1 file changed, 11 insertions(+), 6 deletions(-)
+
+diff --git a/net/9p/trans_fd.c b/net/9p/trans_fd.c
+index 12559c474dde..a0317d459cde 100644
+--- a/net/9p/trans_fd.c
++++ b/net/9p/trans_fd.c
+@@ -292,7 +292,6 @@ static void p9_read_work(struct work_struct *work)
+       __poll_t n;
+       int err;
+       struct p9_conn *m;
+-      int status = REQ_STATUS_ERROR;
+       m = container_of(work, struct p9_conn, rq);
+@@ -375,11 +374,17 @@ static void p9_read_work(struct work_struct *work)
+               p9_debug(P9_DEBUG_TRANS, "got new packet\n");
+               m->rreq->rc.size = m->rc.offset;
+               spin_lock(&m->client->lock);
+-              if (m->rreq->status != REQ_STATUS_ERROR)
+-                      status = REQ_STATUS_RCVD;
+-              list_del(&m->rreq->req_list);
+-              /* update req->status while holding client->lock  */
+-              p9_client_cb(m->client, m->rreq, status);
++              if (m->rreq->status == REQ_STATUS_SENT) {
++                      list_del(&m->rreq->req_list);
++                      p9_client_cb(m->client, m->rreq, REQ_STATUS_RCVD);
++              } else {
++                      spin_unlock(&m->client->lock);
++                      p9_debug(P9_DEBUG_ERROR,
++                               "Request tag %d errored out while we were reading the reply\n",
++                               m->rc.tag);
++                      err = -EIO;
++                      goto error;
++              }
+               spin_unlock(&m->client->lock);
+               m->rc.sdata = NULL;
+               m->rc.offset = 0;
+-- 
+2.20.1
+
diff --git a/queue-4.19/9p-trans_fd-put-worker-reqs-on-destroy.patch b/queue-4.19/9p-trans_fd-put-worker-reqs-on-destroy.patch
new file mode 100644 (file)
index 0000000..dfaa9ae
--- /dev/null
@@ -0,0 +1,45 @@
+From 9208d3efd469cb372f4d2cc9c3813a96a9b75059 Mon Sep 17 00:00:00 2001
+From: Dominique Martinet <dominique.martinet@cea.fr>
+Date: Tue, 9 Oct 2018 11:38:00 +0900
+Subject: 9p/trans_fd: put worker reqs on destroy
+
+[ Upstream commit fb488fc1f2b4c5128540b032892ddec91edaf8d9 ]
+
+p9_read_work/p9_write_work might still hold references to a req after
+having been cancelled; make sure we put any of these to avoid potential
+request leak on disconnect.
+
+Fixes: 728356dedeff8 ("9p: Add refcount to p9_req_t")
+Link: http://lkml.kernel.org/r/1539057956-23741-2-git-send-email-asmadeus@codewreck.org
+Signed-off-by: Dominique Martinet <dominique.martinet@cea.fr>
+Cc: Eric Van Hensbergen <ericvh@gmail.com>
+Cc: Latchesar Ionkov <lucho@ionkov.net>
+Reviewed-by: Tomas Bortoli <tomasbortoli@gmail.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/9p/trans_fd.c | 8 ++++++++
+ 1 file changed, 8 insertions(+)
+
+diff --git a/net/9p/trans_fd.c b/net/9p/trans_fd.c
+index a0317d459cde..f868cf6fba79 100644
+--- a/net/9p/trans_fd.c
++++ b/net/9p/trans_fd.c
+@@ -876,7 +876,15 @@ static void p9_conn_destroy(struct p9_conn *m)
+       p9_mux_poll_stop(m);
+       cancel_work_sync(&m->rq);
++      if (m->rreq) {
++              p9_req_put(m->rreq);
++              m->rreq = NULL;
++      }
+       cancel_work_sync(&m->wq);
++      if (m->wreq) {
++              p9_req_put(m->wreq);
++              m->wreq = NULL;
++      }
+       p9_conn_cancel(m, -ECONNRESET);
+-- 
+2.20.1
+
diff --git a/queue-4.19/9p-use-a-slab-for-allocating-requests.patch b/queue-4.19/9p-use-a-slab-for-allocating-requests.patch
new file mode 100644 (file)
index 0000000..0fde59e
--- /dev/null
@@ -0,0 +1,521 @@
+From a69554b8cb8348d09321240c12d36418eda20d12 Mon Sep 17 00:00:00 2001
+From: Matthew Wilcox <willy@infradead.org>
+Date: Wed, 11 Jul 2018 14:02:24 -0700
+Subject: 9p: Use a slab for allocating requests
+
+[ Upstream commit 996d5b4db4b191f2676cf8775565cab8a5e2753b ]
+
+Replace the custom batch allocation with a slab.  Use an IDR to store
+pointers to the active requests instead of an array.  We don't try to
+handle P9_NOTAG specially; the IDR will happily shrink all the way back
+once the TVERSION call has completed.
+
+Link: http://lkml.kernel.org/r/20180711210225.19730-6-willy@infradead.org
+Signed-off-by: Matthew Wilcox <willy@infradead.org>
+Cc: Eric Van Hensbergen <ericvh@gmail.com>
+Cc: Ron Minnich <rminnich@sandia.gov>
+Cc: Latchesar Ionkov <lucho@ionkov.net>
+Signed-off-by: Dominique Martinet <dominique.martinet@cea.fr>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ include/net/9p/client.h |  51 ++-------
+ net/9p/client.c         | 238 ++++++++++++++--------------------------
+ net/9p/mod.c            |   9 +-
+ 3 files changed, 102 insertions(+), 196 deletions(-)
+
+diff --git a/include/net/9p/client.h b/include/net/9p/client.h
+index 0fa0fbab33b0..a4dc42c53d18 100644
+--- a/include/net/9p/client.h
++++ b/include/net/9p/client.h
+@@ -64,22 +64,15 @@ enum p9_trans_status {
+ /**
+  * enum p9_req_status_t - status of a request
+- * @REQ_STATUS_IDLE: request slot unused
+  * @REQ_STATUS_ALLOC: request has been allocated but not sent
+  * @REQ_STATUS_UNSENT: request waiting to be sent
+  * @REQ_STATUS_SENT: request sent to server
+  * @REQ_STATUS_RCVD: response received from server
+  * @REQ_STATUS_FLSHD: request has been flushed
+  * @REQ_STATUS_ERROR: request encountered an error on the client side
+- *
+- * The @REQ_STATUS_IDLE state is used to mark a request slot as unused
+- * but use is actually tracked by the idpool structure which handles tag
+- * id allocation.
+- *
+  */
+ enum p9_req_status_t {
+-      REQ_STATUS_IDLE,
+       REQ_STATUS_ALLOC,
+       REQ_STATUS_UNSENT,
+       REQ_STATUS_SENT,
+@@ -92,24 +85,12 @@ enum p9_req_status_t {
+  * struct p9_req_t - request slots
+  * @status: status of this request slot
+  * @t_err: transport error
+- * @flush_tag: tag of request being flushed (for flush requests)
+  * @wq: wait_queue for the client to block on for this request
+  * @tc: the request fcall structure
+  * @rc: the response fcall structure
+  * @aux: transport specific data (provided for trans_fd migration)
+  * @req_list: link for higher level objects to chain requests
+- *
+- * Transport use an array to track outstanding requests
+- * instead of a list.  While this may incurr overhead during initial
+- * allocation or expansion, it makes request lookup much easier as the
+- * tag id is a index into an array.  (We use tag+1 so that we can accommodate
+- * the -1 tag for the T_VERSION request).
+- * This also has the nice effect of only having to allocate wait_queues
+- * once, instead of constantly allocating and freeing them.  Its possible
+- * other resources could benefit from this scheme as well.
+- *
+  */
+-
+ struct p9_req_t {
+       int status;
+       int t_err;
+@@ -117,40 +98,26 @@ struct p9_req_t {
+       struct p9_fcall *tc;
+       struct p9_fcall *rc;
+       void *aux;
+-
+       struct list_head req_list;
+ };
+ /**
+  * struct p9_client - per client instance state
+- * @lock: protect @fidlist
++ * @lock: protect @fids and @reqs
+  * @msize: maximum data size negotiated by protocol
+- * @dotu: extension flags negotiated by protocol
+  * @proto_version: 9P protocol version to use
+  * @trans_mod: module API instantiated with this client
++ * @status: connection state
+  * @trans: tranport instance state and API
+  * @fids: All active FID handles
+- * @tagpool - transaction id accounting for session
+- * @reqs - 2D array of requests
+- * @max_tag - current maximum tag id allocated
+- * @name - node name used as client id
++ * @reqs: All active requests.
++ * @name: node name used as client id
+  *
+  * The client structure is used to keep track of various per-client
+  * state that has been instantiated.
+- * In order to minimize per-transaction overhead we use a
+- * simple array to lookup requests instead of a hash table
+- * or linked list.  In order to support larger number of
+- * transactions, we make this a 2D array, allocating new rows
+- * when we need to grow the total number of the transactions.
+- *
+- * Each row is 256 requests and we'll support up to 256 rows for
+- * a total of 64k concurrent requests per session.
+- *
+- * Bugs: duplicated data and potentially unnecessary elements.
+  */
+-
+ struct p9_client {
+-      spinlock_t lock; /* protect client structure */
++      spinlock_t lock;
+       unsigned int msize;
+       unsigned char proto_version;
+       struct p9_trans_module *trans_mod;
+@@ -170,10 +137,7 @@ struct p9_client {
+       } trans_opts;
+       struct idr fids;
+-
+-      struct p9_idpool *tagpool;
+-      struct p9_req_t *reqs[P9_ROW_MAXTAG];
+-      int max_tag;
++      struct idr reqs;
+       char name[__NEW_UTS_LEN + 1];
+ };
+@@ -279,4 +243,7 @@ struct p9_fid *p9_client_xattrwalk(struct p9_fid *, const char *, u64 *);
+ int p9_client_xattrcreate(struct p9_fid *, const char *, u64, int);
+ int p9_client_readlink(struct p9_fid *fid, char **target);
++int p9_client_init(void);
++void p9_client_exit(void);
++
+ #endif /* NET_9P_CLIENT_H */
+diff --git a/net/9p/client.c b/net/9p/client.c
+index 23ec6187dc07..d8949c59d46e 100644
+--- a/net/9p/client.c
++++ b/net/9p/client.c
+@@ -248,132 +248,102 @@ static struct p9_fcall *p9_fcall_alloc(int alloc_msize)
+       return fc;
+ }
++static struct kmem_cache *p9_req_cache;
++
+ /**
+- * p9_tag_alloc - lookup/allocate a request by tag
+- * @c: client session to lookup tag within
+- * @tag: numeric id for transaction
+- *
+- * this is a simple array lookup, but will grow the
+- * request_slots as necessary to accommodate transaction
+- * ids which did not previously have a slot.
+- *
+- * this code relies on the client spinlock to manage locks, its
+- * possible we should switch to something else, but I'd rather
+- * stick with something low-overhead for the common case.
++ * p9_req_alloc - Allocate a new request.
++ * @c: Client session.
++ * @type: Transaction type.
++ * @max_size: Maximum packet size for this request.
+  *
++ * Context: Process context.
++ * Return: Pointer to new request.
+  */
+-
+ static struct p9_req_t *
+-p9_tag_alloc(struct p9_client *c, u16 tag, unsigned int max_size)
++p9_tag_alloc(struct p9_client *c, int8_t type, unsigned int max_size)
+ {
+-      unsigned long flags;
+-      int row, col;
+-      struct p9_req_t *req;
++      struct p9_req_t *req = kmem_cache_alloc(p9_req_cache, GFP_NOFS);
+       int alloc_msize = min(c->msize, max_size);
++      int tag;
+-      /* This looks up the original request by tag so we know which
+-       * buffer to read the data into */
+-      tag++;
+-
+-      if (tag >= c->max_tag) {
+-              spin_lock_irqsave(&c->lock, flags);
+-              /* check again since original check was outside of lock */
+-              while (tag >= c->max_tag) {
+-                      row = (tag / P9_ROW_MAXTAG);
+-                      c->reqs[row] = kcalloc(P9_ROW_MAXTAG,
+-                                      sizeof(struct p9_req_t), GFP_ATOMIC);
+-
+-                      if (!c->reqs[row]) {
+-                              pr_err("Couldn't grow tag array\n");
+-                              spin_unlock_irqrestore(&c->lock, flags);
+-                              return ERR_PTR(-ENOMEM);
+-                      }
+-                      for (col = 0; col < P9_ROW_MAXTAG; col++) {
+-                              req = &c->reqs[row][col];
+-                              req->status = REQ_STATUS_IDLE;
+-                              init_waitqueue_head(&req->wq);
+-                      }
+-                      c->max_tag += P9_ROW_MAXTAG;
+-              }
+-              spin_unlock_irqrestore(&c->lock, flags);
+-      }
+-      row = tag / P9_ROW_MAXTAG;
+-      col = tag % P9_ROW_MAXTAG;
++      if (!req)
++              return NULL;
+-      req = &c->reqs[row][col];
+-      if (!req->tc)
+-              req->tc = p9_fcall_alloc(alloc_msize);
+-      if (!req->rc)
+-              req->rc = p9_fcall_alloc(alloc_msize);
++      req->tc = p9_fcall_alloc(alloc_msize);
++      req->rc = p9_fcall_alloc(alloc_msize);
+       if (!req->tc || !req->rc)
+-              goto grow_failed;
++              goto free;
+       p9pdu_reset(req->tc);
+       p9pdu_reset(req->rc);
+-
+-      req->tc->tag = tag-1;
+       req->status = REQ_STATUS_ALLOC;
++      init_waitqueue_head(&req->wq);
++      INIT_LIST_HEAD(&req->req_list);
++
++      idr_preload(GFP_NOFS);
++      spin_lock_irq(&c->lock);
++      if (type == P9_TVERSION)
++              tag = idr_alloc(&c->reqs, req, P9_NOTAG, P9_NOTAG + 1,
++                              GFP_NOWAIT);
++      else
++              tag = idr_alloc(&c->reqs, req, 0, P9_NOTAG, GFP_NOWAIT);
++      req->tc->tag = tag;
++      spin_unlock_irq(&c->lock);
++      idr_preload_end();
++      if (tag < 0)
++              goto free;
+       return req;
+-grow_failed:
+-      pr_err("Couldn't grow tag array\n");
++free:
+       kfree(req->tc);
+       kfree(req->rc);
+-      req->tc = req->rc = NULL;
++      kmem_cache_free(p9_req_cache, req);
+       return ERR_PTR(-ENOMEM);
+ }
+ /**
+- * p9_tag_lookup - lookup a request by tag
+- * @c: client session to lookup tag within
+- * @tag: numeric id for transaction
++ * p9_tag_lookup - Look up a request by tag.
++ * @c: Client session.
++ * @tag: Transaction ID.
+  *
++ * Context: Any context.
++ * Return: A request, or %NULL if there is no request with that tag.
+  */
+-
+ struct p9_req_t *p9_tag_lookup(struct p9_client *c, u16 tag)
+ {
+-      int row, col;
+-
+-      /* This looks up the original request by tag so we know which
+-       * buffer to read the data into */
+-      tag++;
+-
+-      if (tag >= c->max_tag)
+-              return NULL;
++      struct p9_req_t *req;
+-      row = tag / P9_ROW_MAXTAG;
+-      col = tag % P9_ROW_MAXTAG;
++      rcu_read_lock();
++      req = idr_find(&c->reqs, tag);
++      /* There's no refcount on the req; a malicious server could cause
++       * us to dereference a NULL pointer
++       */
++      rcu_read_unlock();
+-      return &c->reqs[row][col];
++      return req;
+ }
+ EXPORT_SYMBOL(p9_tag_lookup);
+ /**
+- * p9_tag_init - setup tags structure and contents
+- * @c:  v9fs client struct
+- *
+- * This initializes the tags structure for each client instance.
++ * p9_free_req - Free a request.
++ * @c: Client session.
++ * @r: Request to free.
+  *
++ * Context: Any context.
+  */
+-
+-static int p9_tag_init(struct p9_client *c)
++static void p9_free_req(struct p9_client *c, struct p9_req_t *r)
+ {
+-      int err = 0;
++      unsigned long flags;
++      u16 tag = r->tc->tag;
+-      c->tagpool = p9_idpool_create();
+-      if (IS_ERR(c->tagpool)) {
+-              err = PTR_ERR(c->tagpool);
+-              goto error;
+-      }
+-      err = p9_idpool_get(c->tagpool); /* reserve tag 0 */
+-      if (err < 0) {
+-              p9_idpool_destroy(c->tagpool);
+-              goto error;
+-      }
+-      c->max_tag = 0;
+-error:
+-      return err;
++      p9_debug(P9_DEBUG_MUX, "clnt %p req %p tag: %d\n", c, r, tag);
++      spin_lock_irqsave(&c->lock, flags);
++      idr_remove(&c->reqs, tag);
++      spin_unlock_irqrestore(&c->lock, flags);
++      kfree(r->tc);
++      kfree(r->rc);
++      kmem_cache_free(p9_req_cache, r);
+ }
+ /**
+@@ -385,52 +355,15 @@ static int p9_tag_init(struct p9_client *c)
+  */
+ static void p9_tag_cleanup(struct p9_client *c)
+ {
+-      int row, col;
+-
+-      /* check to insure all requests are idle */
+-      for (row = 0; row < (c->max_tag/P9_ROW_MAXTAG); row++) {
+-              for (col = 0; col < P9_ROW_MAXTAG; col++) {
+-                      if (c->reqs[row][col].status != REQ_STATUS_IDLE) {
+-                              p9_debug(P9_DEBUG_MUX,
+-                                       "Attempting to cleanup non-free tag %d,%d\n",
+-                                       row, col);
+-                              /* TODO: delay execution of cleanup */
+-                              return;
+-                      }
+-              }
+-      }
+-
+-      if (c->tagpool) {
+-              p9_idpool_put(0, c->tagpool); /* free reserved tag 0 */
+-              p9_idpool_destroy(c->tagpool);
+-      }
++      struct p9_req_t *req;
++      int id;
+-      /* free requests associated with tags */
+-      for (row = 0; row < (c->max_tag/P9_ROW_MAXTAG); row++) {
+-              for (col = 0; col < P9_ROW_MAXTAG; col++) {
+-                      kfree(c->reqs[row][col].tc);
+-                      kfree(c->reqs[row][col].rc);
+-              }
+-              kfree(c->reqs[row]);
++      rcu_read_lock();
++      idr_for_each_entry(&c->reqs, req, id) {
++              pr_info("Tag %d still in use\n", id);
++              p9_free_req(c, req);
+       }
+-      c->max_tag = 0;
+-}
+-
+-/**
+- * p9_free_req - free a request and clean-up as necessary
+- * c: client state
+- * r: request to release
+- *
+- */
+-
+-static void p9_free_req(struct p9_client *c, struct p9_req_t *r)
+-{
+-      int tag = r->tc->tag;
+-      p9_debug(P9_DEBUG_MUX, "clnt %p req %p tag: %d\n", c, r, tag);
+-
+-      r->status = REQ_STATUS_IDLE;
+-      if (tag != P9_NOTAG && p9_idpool_check(tag, c->tagpool))
+-              p9_idpool_put(tag, c->tagpool);
++      rcu_read_unlock();
+ }
+ /**
+@@ -704,7 +637,7 @@ static struct p9_req_t *p9_client_prepare_req(struct p9_client *c,
+                                             int8_t type, int req_size,
+                                             const char *fmt, va_list ap)
+ {
+-      int tag, err;
++      int err;
+       struct p9_req_t *req;
+       p9_debug(P9_DEBUG_MUX, "client %p op %d\n", c, type);
+@@ -717,24 +650,17 @@ static struct p9_req_t *p9_client_prepare_req(struct p9_client *c,
+       if ((c->status == BeginDisconnect) && (type != P9_TCLUNK))
+               return ERR_PTR(-EIO);
+-      tag = P9_NOTAG;
+-      if (type != P9_TVERSION) {
+-              tag = p9_idpool_get(c->tagpool);
+-              if (tag < 0)
+-                      return ERR_PTR(-ENOMEM);
+-      }
+-
+-      req = p9_tag_alloc(c, tag, req_size);
++      req = p9_tag_alloc(c, type, req_size);
+       if (IS_ERR(req))
+               return req;
+       /* marshall the data */
+-      p9pdu_prepare(req->tc, tag, type);
++      p9pdu_prepare(req->tc, req->tc->tag, type);
+       err = p9pdu_vwritef(req->tc, c->proto_version, fmt, ap);
+       if (err)
+               goto reterr;
+       p9pdu_finalize(c, req->tc);
+-      trace_9p_client_req(c, type, tag);
++      trace_9p_client_req(c, type, req->tc->tag);
+       return req;
+ reterr:
+       p9_free_req(c, req);
+@@ -1040,14 +966,11 @@ struct p9_client *p9_client_create(const char *dev_name, char *options)
+       spin_lock_init(&clnt->lock);
+       idr_init(&clnt->fids);
+-
+-      err = p9_tag_init(clnt);
+-      if (err < 0)
+-              goto free_client;
++      idr_init(&clnt->reqs);
+       err = parse_opts(options, clnt);
+       if (err < 0)
+-              goto destroy_tagpool;
++              goto free_client;
+       if (!clnt->trans_mod)
+               clnt->trans_mod = v9fs_get_default_trans();
+@@ -1056,7 +979,7 @@ struct p9_client *p9_client_create(const char *dev_name, char *options)
+               err = -EPROTONOSUPPORT;
+               p9_debug(P9_DEBUG_ERROR,
+                        "No transport defined or default transport\n");
+-              goto destroy_tagpool;
++              goto free_client;
+       }
+       p9_debug(P9_DEBUG_MUX, "clnt %p trans %p msize %d protocol %d\n",
+@@ -1086,8 +1009,6 @@ struct p9_client *p9_client_create(const char *dev_name, char *options)
+       clnt->trans_mod->close(clnt);
+ put_trans:
+       v9fs_put_trans(clnt->trans_mod);
+-destroy_tagpool:
+-      p9_idpool_destroy(clnt->tagpool);
+ free_client:
+       kfree(clnt);
+       return ERR_PTR(err);
+@@ -2303,3 +2224,14 @@ int p9_client_readlink(struct p9_fid *fid, char **target)
+       return err;
+ }
+ EXPORT_SYMBOL(p9_client_readlink);
++
++int __init p9_client_init(void)
++{
++      p9_req_cache = KMEM_CACHE(p9_req_t, 0);
++      return p9_req_cache ? 0 : -ENOMEM;
++}
++
++void __exit p9_client_exit(void)
++{
++      kmem_cache_destroy(p9_req_cache);
++}
+diff --git a/net/9p/mod.c b/net/9p/mod.c
+index 253ba824a325..0da56d6af73b 100644
+--- a/net/9p/mod.c
++++ b/net/9p/mod.c
+@@ -171,11 +171,17 @@ void v9fs_put_trans(struct p9_trans_module *m)
+  */
+ static int __init init_p9(void)
+ {
++      int ret;
++
++      ret = p9_client_init();
++      if (ret)
++              return ret;
++
+       p9_error_init();
+       pr_info("Installing 9P2000 support\n");
+       p9_trans_fd_init();
+-      return 0;
++      return ret;
+ }
+ /**
+@@ -188,6 +194,7 @@ static void __exit exit_p9(void)
+       pr_info("Unloading 9P2000 support\n");
+       p9_trans_fd_exit();
++      p9_client_exit();
+ }
+ module_init(init_p9)
+-- 
+2.20.1
+
diff --git a/queue-4.19/9p-xen-fix-check-for-xenbus_read-error-in-front_prob.patch b/queue-4.19/9p-xen-fix-check-for-xenbus_read-error-in-front_prob.patch
new file mode 100644 (file)
index 0000000..4538262
--- /dev/null
@@ -0,0 +1,43 @@
+From 8535a8e62b2c7452ddec9c32ed184f35d37bc1fb Mon Sep 17 00:00:00 2001
+From: Dominique Martinet <dominique.martinet@cea.fr>
+Date: Tue, 14 Aug 2018 02:43:48 +0000
+Subject: 9p/xen: fix check for xenbus_read error in front_probe
+
+[ Upstream commit 2f9ad0ac947ccbe3ffe7c6229c9330f2a7755f64 ]
+
+If the xen bus exists but does not expose the proper interface, it is
+possible to get a non-zero length but still some error, leading to
+strcmp failing trying to load invalid memory addresses e.g.
+fffffffffffffffe.
+
+There is then no need to check length when there is no error, as the
+xenbus driver guarantees that the string is nul-terminated.
+
+Link: http://lkml.kernel.org/r/1534236007-10170-1-git-send-email-asmadeus@codewreck.org
+Signed-off-by: Dominique Martinet <dominique.martinet@cea.fr>
+Reviewed-by: Stefano Stabellini <sstabellini@kernel.org>
+Cc: Eric Van Hensbergen <ericvh@gmail.com>
+Cc: Latchesar Ionkov <lucho@ionkov.net>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/9p/trans_xen.c | 4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+diff --git a/net/9p/trans_xen.c b/net/9p/trans_xen.c
+index c2d54ac76bfd..843cb823d9b9 100644
+--- a/net/9p/trans_xen.c
++++ b/net/9p/trans_xen.c
+@@ -391,8 +391,8 @@ static int xen_9pfs_front_probe(struct xenbus_device *dev,
+       unsigned int max_rings, max_ring_order, len = 0;
+       versions = xenbus_read(XBT_NIL, dev->otherend, "versions", &len);
+-      if (!len)
+-              return -EINVAL;
++      if (IS_ERR(versions))
++              return PTR_ERR(versions);
+       if (strcmp(versions, "1")) {
+               kfree(versions);
+               return -EINVAL;
+-- 
+2.20.1
+
diff --git a/queue-4.19/net-9p-include-trans_common.h-to-fix-missing-prototy.patch b/queue-4.19/net-9p-include-trans_common.h-to-fix-missing-prototy.patch
new file mode 100644 (file)
index 0000000..3a1ad7e
--- /dev/null
@@ -0,0 +1,35 @@
+From f46adcd7b195a6d28e36f157fbca17f101ac65fa Mon Sep 17 00:00:00 2001
+From: =?UTF-8?q?Adeodato=20Sim=C3=B3?= <dato@net.com.org.es>
+Date: Tue, 13 Nov 2018 03:28:53 -0300
+Subject: net/9p: include trans_common.h to fix missing prototype warning.
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+[ Upstream commit 52ad259eaac0454c1ac7123e7148cf8d6e6f5301 ]
+
+This silences -Wmissing-prototypes when defining p9_release_pages.
+
+Link: http://lkml.kernel.org/r/b1c4df8f21689b10d451c28fe38e860722d20e71.1542089696.git.dato@net.com.org.es
+Signed-off-by: Adeodato Simó <dato@net.com.org.es>
+Signed-off-by: Dominique Martinet <dominique.martinet@cea.fr>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/9p/trans_common.c | 1 +
+ 1 file changed, 1 insertion(+)
+
+diff --git a/net/9p/trans_common.c b/net/9p/trans_common.c
+index b718db2085b2..3dff68f05fb9 100644
+--- a/net/9p/trans_common.c
++++ b/net/9p/trans_common.c
+@@ -14,6 +14,7 @@
+ #include <linux/mm.h>
+ #include <linux/module.h>
++#include "trans_common.h"
+ /**
+  *  p9_release_pages - Release pages after the transaction.
+-- 
+2.20.1
+
index c04f39b07c6052c545b7ab0195e9c5df78120981..eb2a185f60fc718769db44f41702b308d42da4a2 100644 (file)
@@ -4,3 +4,18 @@ perf-header-fix-unchecked-usage-of-strncpy.patch
 arm64-don-t-unconditionally-add-wno-psabi-to-kbuild_cflags.patch
 revert-x86-uaccess-ftrace-fix-ftrace_likely_update-v.patch
 ib-hfi1-close-psm-sdma_progress-sleep-window.patch
+9p-xen-fix-check-for-xenbus_read-error-in-front_prob.patch
+9p-use-a-slab-for-allocating-requests.patch
+9p-embed-fcall-in-req-to-round-down-buffer-allocs.patch
+9p-add-a-per-client-fcall-kmem_cache.patch
+9p-rename-p9_free_req-function.patch
+9p-add-refcount-to-p9_req_t.patch
+9p-rdma-do-not-disconnect-on-down_interruptible-eaga.patch
+9p-rename-req-to-rreq-in-trans_fd.patch
+9p-acl-fix-uninitialized-iattr-access.patch
+9p-rdma-remove-useless-check-in-cm_event_handler.patch
+9p-p9dirent_read-check-network-provided-name-length.patch
+9p-potential-null-dereference.patch
+9p-trans_fd-abort-p9_read_work-if-req-status-changed.patch
+9p-trans_fd-put-worker-reqs-on-destroy.patch
+net-9p-include-trans_common.h-to-fix-missing-prototy.patch