]> Git Repo - linux.git/commitdiff
Merge tag '9p-for-5.20' of https://github.com/martinetd/linux
authorLinus Torvalds <[email protected]>
Sat, 6 Aug 2022 21:48:54 +0000 (14:48 -0700)
committerLinus Torvalds <[email protected]>
Sat, 6 Aug 2022 21:48:54 +0000 (14:48 -0700)
Pull 9p updates from Dominique Martinet:

 - a couple of fixes

 - add a tracepoint for fid refcounting

 - some cleanup/followup on fid lookup

 - some cleanup around req refcounting

* tag '9p-for-5.20' of https://github.com/martinetd/linux:
  net/9p: Initialize the iounit field during fid creation
  net: 9p: fix refcount leak in p9_read_work() error handling
  9p: roll p9_tag_remove into p9_req_put
  9p: Add client parameter to p9_req_put()
  9p: Drop kref usage
  9p: Fix some kernel-doc comments
  9p fid refcount: cleanup p9_fid_put calls
  9p fid refcount: add a 9p_fid_ref tracepoint
  9p fid refcount: add p9_fid_get/put wrappers
  9p: Fix minor typo in code comment
  9p: Remove unnecessary variable for old fids while walking from d_parent
  9p: Make the path walk logic more clear about when cloning is required
  9p: Track the root fid with its own variable during lookups

1  2 
net/9p/client.c
net/9p/trans_virtio.c

diff --combined net/9p/client.c
index d403085b9ef58853f9affb024ec83cda879fbbcf,3c145a64dc2b1f3a1c38356d1df7472cddb76a84..5bf4dfef0c7010d247e7b6b8b3d113c500cee30a
@@@ -298,14 -298,14 +298,14 @@@ p9_tag_alloc(struct p9_client *c, int8_
        /* 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
+        * in the recv thread, and one ref put by p9_req_put 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);
+       refcount_set(&req->refcount, 2);
  
        return req;
  
@@@ -341,7 -341,7 +341,7 @@@ again
                if (!p9_req_try_get(req))
                        goto again;
                if (req->tc.tag != tag) {
-                       p9_req_put(req);
+                       p9_req_put(c, req);
                        goto again;
                }
        }
@@@ -358,30 -358,28 +358,28 @@@ EXPORT_SYMBOL(p9_tag_lookup)
   *
   * Context: Any context.
   */
- static int p9_tag_remove(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;
  
-       p9_debug(P9_DEBUG_MUX, "clnt %p req %p tag: %d\n", c, r, tag);
+       p9_debug(P9_DEBUG_MUX, "freeing 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);
-       return p9_req_put(r);
  }
  
static void p9_req_free(struct kref *ref)
int p9_req_put(struct p9_client *c, struct p9_req_t *r)
  {
-       struct p9_req_t *r = container_of(ref, struct p9_req_t, refcount);
+       if (refcount_dec_and_test(&r->refcount)) {
+               p9_tag_remove(c, r);
  
-       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);
+               p9_fcall_fini(&r->tc);
+               p9_fcall_fini(&r->rc);
+               kmem_cache_free(p9_req_cache, r);
+               return 1;
+       }
+       return 0;
  }
  EXPORT_SYMBOL(p9_req_put);
  
@@@ -400,7 -398,7 +398,7 @@@ static void p9_tag_cleanup(struct p9_cl
        rcu_read_lock();
        idr_for_each_entry(&c->reqs, req, id) {
                pr_info("Tag %d still in use\n", id);
-               if (p9_tag_remove(c, req) == 0)
+               if (p9_req_put(c, req) == 0)
                        pr_warn("Packet with tag %d has still references",
                                req->tc.tag);
        }
@@@ -426,7 -424,7 +424,7 @@@ void p9_client_cb(struct p9_client *c, 
  
        wake_up(&req->wq);
        p9_debug(P9_DEBUG_MUX, "wakeup: %d\n", req->tc.tag);
-       p9_req_put(req);
+       p9_req_put(c, req);
  }
  EXPORT_SYMBOL(p9_client_cb);
  
@@@ -550,6 -548,90 +548,6 @@@ out_err
        return err;
  }
  
 -/**
 - * p9_check_zc_errors - check 9p packet for error return and process it
 - * @c: current client instance
 - * @req: request to parse and check for error conditions
 - * @uidata: external buffer containing error
 - * @in_hdrlen: Size of response protocol buffer.
 - *
 - * returns error code if one is discovered, otherwise returns 0
 - *
 - * this will have to be more complicated if we have multiple
 - * error packet types
 - */
 -
 -static int p9_check_zc_errors(struct p9_client *c, struct p9_req_t *req,
 -                            struct iov_iter *uidata, int in_hdrlen)
 -{
 -      int err;
 -      int ecode;
 -      s8 type;
 -      char *ename = NULL;
 -
 -      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);
 -      if (err) {
 -              p9_debug(P9_DEBUG_ERROR, "couldn't parse header %d\n", err);
 -              return err;
 -      }
 -
 -      if (type != P9_RERROR && type != P9_RLERROR)
 -              return 0;
 -
 -      if (!p9_is_proto_dotl(c)) {
 -              /* Error is reported in string format */
 -              int len;
 -              /* 7 = header size for RERROR; */
 -              int inline_len = in_hdrlen - 7;
 -
 -              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];
 -              if (len > inline_len) {
 -                      /* We have error in external buffer */
 -                      if (!copy_from_iter_full(ename + inline_len,
 -                                               len - inline_len, uidata)) {
 -                              err = -EFAULT;
 -                              goto out_err;
 -                      }
 -              }
 -              ename = NULL;
 -              err = p9pdu_readf(&req->rc, c->proto_version, "s?d",
 -                                &ename, &ecode);
 -              if (err)
 -                      goto out_err;
 -
 -              if (p9_is_proto_dotu(c) && ecode < 512)
 -                      err = -ecode;
 -
 -              if (!err) {
 -                      err = p9_errstr2errno(ename, strlen(ename));
 -
 -                      p9_debug(P9_DEBUG_9P, "<<< RERROR (%d) %s\n",
 -                               -ecode, ename);
 -              }
 -              kfree(ename);
 -      } else {
 -              err = p9pdu_readf(&req->rc, c->proto_version, "d", &ecode);
 -              err = -ecode;
 -
 -              p9_debug(P9_DEBUG_9P, "<<< RLERROR (%d)\n", -ecode);
 -      }
 -      return err;
 -
 -out_err:
 -      p9_debug(P9_DEBUG_ERROR, "couldn't parse error%d\n", err);
 -      return err;
 -}
 -
  static struct p9_req_t *
  p9_client_rpc(struct p9_client *c, int8_t type, const char *fmt, ...);
  
@@@ -589,7 -671,7 +587,7 @@@ static int p9_client_flush(struct p9_cl
                        c->trans_mod->cancelled(c, oldreq);
        }
  
-       p9_tag_remove(c, req);
+       p9_req_put(c, req);
        return 0;
  }
  
@@@ -623,9 -705,9 +621,9 @@@ static struct p9_req_t *p9_client_prepa
        trace_9p_client_req(c, type, req->tc.tag);
        return req;
  reterr:
-       p9_tag_remove(c, req);
+       p9_req_put(c, req);
        /* We have to put also the 2nd reference as it won't be used */
-       p9_req_put(req);
+       p9_req_put(c, req);
        return ERR_PTR(err);
  }
  
   * @type: type of request
   * @fmt: protocol format string (see protocol.c)
   *
-  * Returns request structure (which client must free using p9_tag_remove)
+  * Returns request structure (which client must free using p9_req_put)
   */
  
  static struct p9_req_t *
@@@ -662,7 -744,7 +660,7 @@@ p9_client_rpc(struct p9_client *c, int8
        err = c->trans_mod->request(c, req);
        if (err < 0) {
                /* write won't happen */
-               p9_req_put(req);
+               p9_req_put(c, req);
                if (err != -ERESTARTSYS && err != -EFAULT)
                        c->status = Disconnected;
                goto recalc_sigpending;
@@@ -713,7 -795,7 +711,7 @@@ recalc_sigpending
        if (!err)
                return req;
  reterr:
-       p9_tag_remove(c, req);
+       p9_req_put(c, req);
        return ERR_PTR(safe_errno(err));
  }
  
   * @in_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_tag_remove)
+  * Returns request structure (which client must free using p9_req_put)
   */
  static struct p9_req_t *p9_client_zc_rpc(struct p9_client *c, int8_t type,
                                         struct iov_iter *uidata,
@@@ -790,12 -872,12 +788,12 @@@ recalc_sigpending
        if (err < 0)
                goto reterr;
  
 -      err = p9_check_zc_errors(c, req, uidata, in_hdrlen);
 +      err = p9_check_errors(c, req);
        trace_9p_client_res(c, type, req->rc.tag, err);
        if (!err)
                return req;
  reterr:
-       p9_tag_remove(c, req);
+       p9_req_put(c, req);
        return ERR_PTR(safe_errno(err));
  }
  
@@@ -805,16 -887,13 +803,13 @@@ static struct p9_fid *p9_fid_create(str
        struct p9_fid *fid;
  
        p9_debug(P9_DEBUG_FID, "clnt %p\n", clnt);
-       fid = kmalloc(sizeof(*fid), GFP_KERNEL);
+       fid = kzalloc(sizeof(*fid), GFP_KERNEL);
        if (!fid)
                return NULL;
  
-       memset(&fid->qid, 0, sizeof(fid->qid));
        fid->mode = -1;
        fid->uid = current_fsuid();
        fid->clnt = clnt;
-       fid->rdir = NULL;
-       fid->fid = 0;
        refcount_set(&fid->count, 1);
  
        idr_preload(GFP_KERNEL);
                            GFP_NOWAIT);
        spin_unlock_irq(&clnt->lock);
        idr_preload_end();
-       if (!ret)
+       if (!ret) {
+               trace_9p_fid_ref(fid, P9_FID_REF_CREATE);
                return fid;
+       }
  
        kfree(fid);
        return NULL;
@@@ -836,6 -917,7 +833,7 @@@ static void p9_fid_destroy(struct p9_fi
        unsigned long flags;
  
        p9_debug(P9_DEBUG_FID, "fid %d\n", fid->fid);
+       trace_9p_fid_ref(fid, P9_FID_REF_DESTROY);
        clnt = fid->clnt;
        spin_lock_irqsave(&clnt->lock, flags);
        idr_remove(&clnt->fids, fid->fid);
        kfree(fid);
  }
  
+ /* We also need to export tracepoint symbols for tracepoint_enabled() */
+ EXPORT_TRACEPOINT_SYMBOL(9p_fid_ref);
+ void do_trace_9p_fid_get(struct p9_fid *fid)
+ {
+       trace_9p_fid_ref(fid, P9_FID_REF_GET);
+ }
+ EXPORT_SYMBOL(do_trace_9p_fid_get);
+ void do_trace_9p_fid_put(struct p9_fid *fid)
+ {
+       trace_9p_fid_ref(fid, P9_FID_REF_PUT);
+ }
+ EXPORT_SYMBOL(do_trace_9p_fid_put);
  static int p9_client_version(struct p9_client *c)
  {
        int err = 0;
  
  error:
        kfree(version);
-       p9_tag_remove(c, req);
+       p9_req_put(c, req);
  
        return err;
  }
@@@ -1060,7 -1157,7 +1073,7 @@@ struct p9_fid *p9_client_attach(struct 
        err = p9pdu_readf(&req->rc, clnt->proto_version, "Q", &qid);
        if (err) {
                trace_9p_protocol_dump(clnt, &req->rc);
-               p9_tag_remove(clnt, req);
+               p9_req_put(clnt, req);
                goto error;
        }
  
  
        memmove(&fid->qid, &qid, sizeof(struct p9_qid));
  
-       p9_tag_remove(clnt, req);
+       p9_req_put(clnt, req);
        return fid;
  
  error:
@@@ -1116,10 -1213,10 +1129,10 @@@ struct p9_fid *p9_client_walk(struct p9
        err = p9pdu_readf(&req->rc, clnt->proto_version, "R", &nwqids, &wqids);
        if (err) {
                trace_9p_protocol_dump(clnt, &req->rc);
-               p9_tag_remove(clnt, req);
+               p9_req_put(clnt, req);
                goto clunk_fid;
        }
-       p9_tag_remove(clnt, req);
+       p9_req_put(clnt, req);
  
        p9_debug(P9_DEBUG_9P, "<<< RWALK nwqid %d:\n", nwqids);
  
  
  clunk_fid:
        kfree(wqids);
-       p9_client_clunk(fid);
+       p9_fid_put(fid);
        fid = NULL;
  
  error:
@@@ -1195,7 -1292,7 +1208,7 @@@ int p9_client_open(struct p9_fid *fid, 
        fid->iounit = iounit;
  
  free_and_error:
-       p9_tag_remove(clnt, req);
+       p9_req_put(clnt, req);
  error:
        return err;
  }
@@@ -1239,7 -1336,7 +1252,7 @@@ int p9_client_create_dotl(struct p9_fi
        ofid->iounit = iounit;
  
  free_and_error:
-       p9_tag_remove(clnt, req);
+       p9_req_put(clnt, req);
  error:
        return err;
  }
@@@ -1283,7 -1380,7 +1296,7 @@@ int p9_client_fcreate(struct p9_fid *fi
        fid->iounit = iounit;
  
  free_and_error:
-       p9_tag_remove(clnt, req);
+       p9_req_put(clnt, req);
  error:
        return err;
  }
@@@ -1317,7 -1414,7 +1330,7 @@@ int p9_client_symlink(struct p9_fid *df
                 qid->type, qid->path, qid->version);
  
  free_and_error:
-       p9_tag_remove(clnt, req);
+       p9_req_put(clnt, req);
  error:
        return err;
  }
@@@ -1337,7 -1434,7 +1350,7 @@@ int p9_client_link(struct p9_fid *dfid
                return PTR_ERR(req);
  
        p9_debug(P9_DEBUG_9P, "<<< RLINK\n");
-       p9_tag_remove(clnt, req);
+       p9_req_put(clnt, req);
        return 0;
  }
  EXPORT_SYMBOL(p9_client_link);
@@@ -1361,7 -1458,7 +1374,7 @@@ int p9_client_fsync(struct p9_fid *fid
  
        p9_debug(P9_DEBUG_9P, "<<< RFSYNC fid %d\n", fid->fid);
  
-       p9_tag_remove(clnt, req);
+       p9_req_put(clnt, req);
  
  error:
        return err;
@@@ -1375,15 -1472,6 +1388,6 @@@ int p9_client_clunk(struct p9_fid *fid
        struct p9_req_t *req;
        int retries = 0;
  
-       if (!fid || IS_ERR(fid)) {
-               pr_warn("%s (%d): Trying to clunk with invalid fid\n",
-                       __func__, task_pid_nr(current));
-               dump_stack();
-               return 0;
-       }
-       if (!refcount_dec_and_test(&fid->count))
-               return 0;
  again:
        p9_debug(P9_DEBUG_9P, ">>> TCLUNK fid %d (try %d)\n",
                 fid->fid, retries);
  
        p9_debug(P9_DEBUG_9P, "<<< RCLUNK fid %d\n", fid->fid);
  
-       p9_tag_remove(clnt, req);
+       p9_req_put(clnt, req);
  error:
        /* Fid is not valid even after a failed clunk
         * If interrupted, retry once then give up and
@@@ -1432,10 -1520,10 +1436,10 @@@ int p9_client_remove(struct p9_fid *fid
  
        p9_debug(P9_DEBUG_9P, "<<< RREMOVE fid %d\n", fid->fid);
  
-       p9_tag_remove(clnt, req);
+       p9_req_put(clnt, req);
  error:
        if (err == -ERESTARTSYS)
-               p9_client_clunk(fid);
+               p9_fid_put(fid);
        else
                p9_fid_destroy(fid);
        return err;
@@@ -1459,7 -1547,7 +1463,7 @@@ int p9_client_unlinkat(struct p9_fid *d
        }
        p9_debug(P9_DEBUG_9P, "<<< RUNLINKAT fid %d %s\n", dfid->fid, name);
  
-       p9_tag_remove(clnt, req);
+       p9_req_put(clnt, req);
  error:
        return err;
  }
@@@ -1527,7 -1615,7 +1531,7 @@@ p9_client_read_once(struct p9_fid *fid
                           "D", &count, &dataptr);
        if (*err) {
                trace_9p_protocol_dump(clnt, &req->rc);
-               p9_tag_remove(clnt, req);
+               p9_req_put(clnt, req);
                return 0;
        }
        if (rsize < count) {
  
                if (n != count) {
                        *err = -EFAULT;
-                       p9_tag_remove(clnt, req);
+                       p9_req_put(clnt, req);
                        return n;
                }
        } else {
                iov_iter_advance(to, count);
        }
-       p9_tag_remove(clnt, req);
+       p9_req_put(clnt, req);
        return count;
  }
  EXPORT_SYMBOL(p9_client_read_once);
@@@ -1591,7 -1679,7 +1595,7 @@@ p9_client_write(struct p9_fid *fid, u6
                *err = p9pdu_readf(&req->rc, clnt->proto_version, "d", &count);
                if (*err) {
                        trace_9p_protocol_dump(clnt, &req->rc);
-                       p9_tag_remove(clnt, req);
+                       p9_req_put(clnt, req);
                        break;
                }
                if (rsize < count) {
  
                p9_debug(P9_DEBUG_9P, "<<< RWRITE count %d\n", count);
  
-               p9_tag_remove(clnt, req);
+               p9_req_put(clnt, req);
                iov_iter_advance(from, count);
                total += count;
                offset += count;
@@@ -1636,7 -1724,7 +1640,7 @@@ struct p9_wstat *p9_client_stat(struct 
        err = p9pdu_readf(&req->rc, clnt->proto_version, "wS", &ignored, ret);
        if (err) {
                trace_9p_protocol_dump(clnt, &req->rc);
-               p9_tag_remove(clnt, req);
+               p9_req_put(clnt, req);
                goto error;
        }
  
                 from_kgid(&init_user_ns, ret->n_gid),
                 from_kuid(&init_user_ns, ret->n_muid));
  
-       p9_tag_remove(clnt, req);
+       p9_req_put(clnt, req);
        return ret;
  
  error:
@@@ -1689,7 -1777,7 +1693,7 @@@ struct p9_stat_dotl *p9_client_getattr_
        err = p9pdu_readf(&req->rc, clnt->proto_version, "A", ret);
        if (err) {
                trace_9p_protocol_dump(clnt, &req->rc);
-               p9_tag_remove(clnt, req);
+               p9_req_put(clnt, req);
                goto error;
        }
  
                 ret->st_btime_sec, ret->st_btime_nsec,
                 ret->st_gen, ret->st_data_version);
  
-       p9_tag_remove(clnt, req);
+       p9_req_put(clnt, req);
        return ret;
  
  error:
@@@ -1787,7 -1875,7 +1791,7 @@@ int p9_client_wstat(struct p9_fid *fid
  
        p9_debug(P9_DEBUG_9P, "<<< RWSTAT fid %d\n", fid->fid);
  
-       p9_tag_remove(clnt, req);
+       p9_req_put(clnt, req);
  error:
        return err;
  }
@@@ -1819,7 -1907,7 +1823,7 @@@ int p9_client_setattr(struct p9_fid *fi
                goto error;
        }
        p9_debug(P9_DEBUG_9P, "<<< RSETATTR fid %d\n", fid->fid);
-       p9_tag_remove(clnt, req);
+       p9_req_put(clnt, req);
  error:
        return err;
  }
@@@ -1847,7 -1935,7 +1851,7 @@@ int p9_client_statfs(struct p9_fid *fid
                          &sb->files, &sb->ffree, &sb->fsid, &sb->namelen);
        if (err) {
                trace_9p_protocol_dump(clnt, &req->rc);
-               p9_tag_remove(clnt, req);
+               p9_req_put(clnt, req);
                goto error;
        }
  
                 fid->fid, sb->type, sb->bsize, sb->blocks, sb->bfree,
                 sb->bavail, sb->files, sb->ffree, sb->fsid, sb->namelen);
  
-       p9_tag_remove(clnt, req);
+       p9_req_put(clnt, req);
  error:
        return err;
  }
@@@ -1884,7 -1972,7 +1888,7 @@@ int p9_client_rename(struct p9_fid *fid
  
        p9_debug(P9_DEBUG_9P, "<<< RRENAME fid %d\n", fid->fid);
  
-       p9_tag_remove(clnt, req);
+       p9_req_put(clnt, req);
  error:
        return err;
  }
@@@ -1914,7 -2002,7 +1918,7 @@@ int p9_client_renameat(struct p9_fid *o
        p9_debug(P9_DEBUG_9P, "<<< RRENAMEAT newdirfid %d new name %s\n",
                 newdirfid->fid, new_name);
  
-       p9_tag_remove(clnt, req);
+       p9_req_put(clnt, req);
  error:
        return err;
  }
@@@ -1950,15 -2038,15 +1954,15 @@@ struct p9_fid *p9_client_xattrwalk(stru
        err = p9pdu_readf(&req->rc, clnt->proto_version, "q", attr_size);
        if (err) {
                trace_9p_protocol_dump(clnt, &req->rc);
-               p9_tag_remove(clnt, req);
+               p9_req_put(clnt, req);
                goto clunk_fid;
        }
-       p9_tag_remove(clnt, req);
+       p9_req_put(clnt, req);
        p9_debug(P9_DEBUG_9P, "<<<  RXATTRWALK fid %d size %llu\n",
                 attr_fid->fid, *attr_size);
        return attr_fid;
  clunk_fid:
-       p9_client_clunk(attr_fid);
+       p9_fid_put(attr_fid);
        attr_fid = NULL;
  error:
        if (attr_fid && attr_fid != file_fid)
@@@ -1987,7 -2075,7 +1991,7 @@@ int p9_client_xattrcreate(struct p9_fi
                goto error;
        }
        p9_debug(P9_DEBUG_9P, "<<< RXATTRCREATE fid %d\n", fid->fid);
-       p9_tag_remove(clnt, req);
+       p9_req_put(clnt, req);
  error:
        return err;
  }
@@@ -2049,11 -2137,11 +2053,11 @@@ int p9_client_readdir(struct p9_fid *fi
        if (non_zc)
                memmove(data, dataptr, count);
  
-       p9_tag_remove(clnt, req);
+       p9_req_put(clnt, req);
        return count;
  
  free_and_error:
-       p9_tag_remove(clnt, req);
+       p9_req_put(clnt, req);
  error:
        return err;
  }
@@@ -2085,7 -2173,7 +2089,7 @@@ int p9_client_mknod_dotl(struct p9_fid 
                 qid->type, qid->path, qid->version);
  
  error:
-       p9_tag_remove(clnt, req);
+       p9_req_put(clnt, req);
        return err;
  }
  EXPORT_SYMBOL(p9_client_mknod_dotl);
@@@ -2115,7 -2203,7 +2119,7 @@@ int p9_client_mkdir_dotl(struct p9_fid 
                 qid->path, qid->version);
  
  error:
-       p9_tag_remove(clnt, req);
+       p9_req_put(clnt, req);
        return err;
  }
  EXPORT_SYMBOL(p9_client_mkdir_dotl);
@@@ -2147,7 -2235,7 +2151,7 @@@ int p9_client_lock_dotl(struct p9_fid *
        }
        p9_debug(P9_DEBUG_9P, "<<< RLOCK status %i\n", *status);
  error:
-       p9_tag_remove(clnt, req);
+       p9_req_put(clnt, req);
        return err;
  }
  EXPORT_SYMBOL(p9_client_lock_dotl);
@@@ -2184,7 -2272,7 +2188,7 @@@ int p9_client_getlock_dotl(struct p9_fi
                 glock->type, glock->start, glock->length,
                 glock->proc_id, glock->client_id);
  error:
-       p9_tag_remove(clnt, req);
+       p9_req_put(clnt, req);
        return err;
  }
  EXPORT_SYMBOL(p9_client_getlock_dotl);
@@@ -2210,7 -2298,7 +2214,7 @@@ int p9_client_readlink(struct p9_fid *f
        }
        p9_debug(P9_DEBUG_9P, "<<< RREADLINK target %s\n", *target);
  error:
-       p9_tag_remove(clnt, req);
+       p9_req_put(clnt, req);
        return err;
  }
  EXPORT_SYMBOL(p9_client_readlink);
diff --combined net/9p/trans_virtio.c
index 2a210c2f8e403e29f018d8aa8cdb6db380abc7c4,147972bf2e797ad81ac17644e56d3cd2df6cf554..03770addaa5c98deff40435094bcdfe53b828c0a
@@@ -199,7 -199,7 +199,7 @@@ static int p9_virtio_cancel(struct p9_c
  /* 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);
+       p9_req_put(client, req);
        return 0;
  }
  
@@@ -377,35 -377,6 +377,35 @@@ static int p9_get_mapped_pages(struct v
        }
  }
  
 +static void handle_rerror(struct p9_req_t *req, int in_hdr_len,
 +                        size_t offs, struct page **pages)
 +{
 +      unsigned size, n;
 +      void *to = req->rc.sdata + in_hdr_len;
 +
 +      // Fits entirely into the static data?  Nothing to do.
 +      if (req->rc.size < in_hdr_len)
 +              return;
 +
 +      // Really long error message?  Tough, truncate the reply.  Might get
 +      // rejected (we can't be arsed to adjust the size encoded in header,
 +      // or string size for that matter), but it wouldn't be anything valid
 +      // anyway.
 +      if (unlikely(req->rc.size > P9_ZC_HDR_SZ))
 +              req->rc.size = P9_ZC_HDR_SZ;
 +
 +      // data won't span more than two pages
 +      size = req->rc.size - in_hdr_len;
 +      n = PAGE_SIZE - offs;
 +      if (size > n) {
 +              memcpy_from_page(to, *pages++, offs, n);
 +              offs = 0;
 +              to += n;
 +              size -= n;
 +      }
 +      memcpy_from_page(to, *pages, offs, size);
 +}
 +
  /**
   * p9_virtio_zc_request - issue a zero copy request
   * @client: client instance issuing the request
@@@ -532,11 -503,6 +532,11 @@@ req_retry_pinned
        kicked = 1;
        p9_debug(P9_DEBUG_TRANS, "virtio request kicked\n");
        err = wait_event_killable(req->wq, req->status >= REQ_STATUS_RCVD);
 +      // RERROR needs reply (== error string) in static data
 +      if (req->status == REQ_STATUS_RCVD &&
 +          unlikely(req->rc.sdata[4] == P9_RERROR))
 +              handle_rerror(req, in_hdr_len, offs, in_pages);
 +
        /*
         * Non kernel buffers are pinned, unpin them
         */
@@@ -557,7 -523,7 +557,7 @@@ err_out
        kvfree(out_pages);
        if (!kicked) {
                /* reply won't come */
-               p9_req_put(req);
+               p9_req_put(client, req);
        }
        return err;
  }
This page took 0.089387 seconds and 4 git commands to generate.