Rework and error handling fixes, primarily in the fscatch and fd transports.

-----BEGIN PGP SIGNATURE-----
 Comment: GPGTools - http://gpgtools.org
 
 iQIcBAABAgAGBQJWpRmuAAoJEDZk62b0Tg6xnXYP/3nukU7v56M+jTI32XqxKRXb
 BtyuOFGxwp0K3pDdtupQs9My1n11zwcN+A15pWQtHjDSY466pX8LJlGUD1aZ9x5A
 YHofrRmjFauo61CKSxiIrWt4kO1i/fs5SAoihMsjIT4XBIVS+Snp6uIKY/1Lz60L
 h+FJlQr1cGXSwkt+w0aqt5VfvD0zpnpIzzFuB2etyDnzZMzr8SsRjTxo6PoTQsQJ
 FQwOFI/J0jBTeLE7WBCCf/25vFRVw/IlCkby4SFvIDpW2CdfYYLD2lljiHho7qwg
 2ur5erfVBK8VR4Mo5psdObggq/VUxi2yQyuBRYbVj2dD0WbTfavsgo7qzR4glhFH
 /KapL39V3nEVVjoKmMBV0OsnWUq+EokXtozqHX3Omc2MNldin2NgA6zTw5sIeoKo
 PhrhiERwllSGh91cKxtCt9FYIRF6jCHUYzXoZCNcuhMnOJfonFJZ6fyoVuDUJDCM
 pFWqpGJ/6KVLi8yjNS9fKw82EApvqoFQu+YtS2/IlMXFuJXPCv094kuRCMEFYRxE
 NJ50eQz9/F4SuGcM7Wlg6ESaZB4bWrpQOpdsgnPvZzqy6zGbitCNpTvT4yc1Ui2W
 pddzvEmRlEdzBrHCvDqQ4z3pYSA5KDZk1sQOB819JF+gzk5rjhlfXQDJ4yJR9wcu
 Csu1aBh565evjw9MIO1G
 =32IE
 -----END PGP SIGNATURE-----

Merge tag 'for-linus-4.5-merge-window' of git://git.kernel.org/pub/scm/linux/kernel/git/ericvh/v9fs

Pull 9p updates from Eric Van Hensbergen:
 "Sorry for the last minute pull request, there's was a change that
  didn't get pulled into for-next until two weeks ago and I wanted to
  give it some bake time.

  Summary:

  Rework and error handling fixes, primarily in the fscatch and fd
  transports"

* tag 'for-linus-4.5-merge-window' of git://git.kernel.org/pub/scm/linux/kernel/git/ericvh/v9fs:
  fs/9p: use fscache mutex rather than spinlock
  9p: trans_fd, bail out if recv fcall if missing
  9p: trans_fd, read rework to use p9_parse_header
  net/9p: Add device name details on error
This commit is contained in:
Linus Torvalds 2016-01-24 12:39:09 -08:00
commit c52cb4311f
2 changed files with 47 additions and 43 deletions

View File

@ -108,9 +108,7 @@ struct p9_poll_wait {
* @unsent_req_list: accounting for requests that haven't been sent * @unsent_req_list: accounting for requests that haven't been sent
* @req: current request being processed (if any) * @req: current request being processed (if any)
* @tmp_buf: temporary buffer to read in header * @tmp_buf: temporary buffer to read in header
* @rsize: amount to read for current frame * @rc: temporary fcall for reading current frame
* @rpos: read position in current frame
* @rbuf: current read buffer
* @wpos: write position for current frame * @wpos: write position for current frame
* @wsize: amount of data to write for current frame * @wsize: amount of data to write for current frame
* @wbuf: current write buffer * @wbuf: current write buffer
@ -131,9 +129,7 @@ struct p9_conn {
struct list_head unsent_req_list; struct list_head unsent_req_list;
struct p9_req_t *req; struct p9_req_t *req;
char tmp_buf[7]; char tmp_buf[7];
int rsize; struct p9_fcall rc;
int rpos;
char *rbuf;
int wpos; int wpos;
int wsize; int wsize;
char *wbuf; char *wbuf;
@ -305,69 +301,77 @@ static void p9_read_work(struct work_struct *work)
if (m->err < 0) if (m->err < 0)
return; return;
p9_debug(P9_DEBUG_TRANS, "start mux %p pos %d\n", m, m->rpos); p9_debug(P9_DEBUG_TRANS, "start mux %p pos %zd\n", m, m->rc.offset);
if (!m->rbuf) { if (!m->rc.sdata) {
m->rbuf = m->tmp_buf; m->rc.sdata = m->tmp_buf;
m->rpos = 0; m->rc.offset = 0;
m->rsize = 7; /* start by reading header */ m->rc.capacity = 7; /* start by reading header */
} }
clear_bit(Rpending, &m->wsched); clear_bit(Rpending, &m->wsched);
p9_debug(P9_DEBUG_TRANS, "read mux %p pos %d size: %d = %d\n", p9_debug(P9_DEBUG_TRANS, "read mux %p pos %zd size: %zd = %zd\n",
m, m->rpos, m->rsize, m->rsize-m->rpos); m, m->rc.offset, m->rc.capacity,
err = p9_fd_read(m->client, m->rbuf + m->rpos, m->rc.capacity - m->rc.offset);
m->rsize - m->rpos); err = p9_fd_read(m->client, m->rc.sdata + m->rc.offset,
m->rc.capacity - m->rc.offset);
p9_debug(P9_DEBUG_TRANS, "mux %p got %d bytes\n", m, err); p9_debug(P9_DEBUG_TRANS, "mux %p got %d bytes\n", m, err);
if (err == -EAGAIN) { if (err == -EAGAIN)
goto end_clear; goto end_clear;
}
if (err <= 0) if (err <= 0)
goto error; goto error;
m->rpos += err; m->rc.offset += err;
if ((!m->req) && (m->rpos == m->rsize)) { /* header read in */ /* header read in */
u16 tag; if ((!m->req) && (m->rc.offset == m->rc.capacity)) {
p9_debug(P9_DEBUG_TRANS, "got new header\n"); p9_debug(P9_DEBUG_TRANS, "got new header\n");
n = le32_to_cpu(*(__le32 *) m->rbuf); /* read packet size */ err = p9_parse_header(&m->rc, NULL, NULL, NULL, 0);
if (n >= m->client->msize) { if (err) {
p9_debug(P9_DEBUG_ERROR, p9_debug(P9_DEBUG_ERROR,
"requested packet size too big: %d\n", n); "error parsing header: %d\n", err);
goto error;
}
if (m->rc.size >= m->client->msize) {
p9_debug(P9_DEBUG_ERROR,
"requested packet size too big: %d\n",
m->rc.size);
err = -EIO; err = -EIO;
goto error; goto error;
} }
tag = le16_to_cpu(*(__le16 *) (m->rbuf+5)); /* read tag */
p9_debug(P9_DEBUG_TRANS, p9_debug(P9_DEBUG_TRANS,
"mux %p pkt: size: %d bytes tag: %d\n", m, n, tag); "mux %p pkt: size: %d bytes tag: %d\n",
m, m->rc.size, m->rc.tag);
m->req = p9_tag_lookup(m->client, tag); m->req = p9_tag_lookup(m->client, m->rc.tag);
if (!m->req || (m->req->status != REQ_STATUS_SENT)) { if (!m->req || (m->req->status != REQ_STATUS_SENT)) {
p9_debug(P9_DEBUG_ERROR, "Unexpected packet tag %d\n", p9_debug(P9_DEBUG_ERROR, "Unexpected packet tag %d\n",
tag); m->rc.tag);
err = -EIO; err = -EIO;
goto error; goto error;
} }
if (m->req->rc == NULL) { if (m->req->rc == NULL) {
m->req->rc = kmalloc(sizeof(struct p9_fcall) + p9_debug(P9_DEBUG_ERROR,
m->client->msize, GFP_NOFS); "No recv fcall for tag %d (req %p), disconnecting!\n",
if (!m->req->rc) { m->rc.tag, m->req);
m->req = NULL; m->req = NULL;
err = -ENOMEM; err = -EIO;
goto error; goto error;
} }
} m->rc.sdata = (char *)m->req->rc + sizeof(struct p9_fcall);
m->rbuf = (char *)m->req->rc + sizeof(struct p9_fcall); memcpy(m->rc.sdata, m->tmp_buf, m->rc.capacity);
memcpy(m->rbuf, m->tmp_buf, m->rsize); m->rc.capacity = m->rc.size;
m->rsize = n;
} }
/* not an else because some packets (like clunk) have no payload */ /* packet is read in
if ((m->req) && (m->rpos == m->rsize)) { /* packet is read in */ * not an else because some packets (like clunk) have no payload
*/
if ((m->req) && (m->rc.offset == m->rc.capacity)) {
p9_debug(P9_DEBUG_TRANS, "got new packet\n"); p9_debug(P9_DEBUG_TRANS, "got new packet\n");
spin_lock(&m->client->lock); spin_lock(&m->client->lock);
if (m->req->status != REQ_STATUS_ERROR) if (m->req->status != REQ_STATUS_ERROR)
@ -375,9 +379,9 @@ static void p9_read_work(struct work_struct *work)
list_del(&m->req->req_list); list_del(&m->req->req_list);
spin_unlock(&m->client->lock); spin_unlock(&m->client->lock);
p9_client_cb(m->client, m->req, status); p9_client_cb(m->client, m->req, status);
m->rbuf = NULL; m->rc.sdata = NULL;
m->rpos = 0; m->rc.offset = 0;
m->rsize = 0; m->rc.capacity = 0;
m->req = NULL; m->req = NULL;
} }

View File

@ -658,7 +658,7 @@ p9_virtio_create(struct p9_client *client, const char *devname, char *args)
mutex_unlock(&virtio_9p_lock); mutex_unlock(&virtio_9p_lock);
if (!found) { if (!found) {
pr_err("no channels available\n"); pr_err("no channels available for device %s\n", devname);
return ret; return ret;
} }