Commit 0488713c authored by Linus Torvalds's avatar Linus Torvalds

Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/ericvh/v9fs

* 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/ericvh/v9fs:
  net/9p: handle correctly interrupted 9P requests
  net/9p: return error when p9_client_stat fails
  net/9p: set correct stat size when sending Twstat messages
parents 37ecfd80 1bab88b2
...@@ -98,7 +98,6 @@ enum p9_req_status_t { ...@@ -98,7 +98,6 @@ enum p9_req_status_t {
struct p9_req_t { struct p9_req_t {
int status; int status;
int t_err; int t_err;
u16 flush_tag;
wait_queue_head_t *wq; wait_queue_head_t *wq;
struct p9_fcall *tc; struct p9_fcall *tc;
struct p9_fcall *rc; struct p9_fcall *rc;
......
...@@ -203,7 +203,6 @@ static struct p9_req_t *p9_tag_alloc(struct p9_client *c, u16 tag) ...@@ -203,7 +203,6 @@ static struct p9_req_t *p9_tag_alloc(struct p9_client *c, u16 tag)
p9pdu_reset(req->tc); p9pdu_reset(req->tc);
p9pdu_reset(req->rc); p9pdu_reset(req->rc);
req->flush_tag = 0;
req->tc->tag = tag-1; req->tc->tag = tag-1;
req->status = REQ_STATUS_ALLOC; req->status = REQ_STATUS_ALLOC;
...@@ -324,35 +323,9 @@ static void p9_free_req(struct p9_client *c, struct p9_req_t *r) ...@@ -324,35 +323,9 @@ static void p9_free_req(struct p9_client *c, struct p9_req_t *r)
*/ */
void p9_client_cb(struct p9_client *c, struct p9_req_t *req) void p9_client_cb(struct p9_client *c, struct p9_req_t *req)
{ {
struct p9_req_t *other_req;
unsigned long flags;
P9_DPRINTK(P9_DEBUG_MUX, " tag %d\n", req->tc->tag); P9_DPRINTK(P9_DEBUG_MUX, " tag %d\n", req->tc->tag);
wake_up(req->wq);
if (req->status == REQ_STATUS_ERROR) P9_DPRINTK(P9_DEBUG_MUX, "wakeup: %d\n", req->tc->tag);
wake_up(req->wq);
if (req->flush_tag) { /* flush receive path */
P9_DPRINTK(P9_DEBUG_9P, "<<< RFLUSH %d\n", req->tc->tag);
spin_lock_irqsave(&c->lock, flags);
other_req = p9_tag_lookup(c, req->flush_tag);
if (other_req->status != REQ_STATUS_FLSH) /* stale flush */
spin_unlock_irqrestore(&c->lock, flags);
else {
other_req->status = REQ_STATUS_FLSHD;
spin_unlock_irqrestore(&c->lock, flags);
wake_up(other_req->wq);
}
p9_free_req(c, req);
} else { /* normal receive path */
P9_DPRINTK(P9_DEBUG_MUX, "normal: tag %d\n", req->tc->tag);
spin_lock_irqsave(&c->lock, flags);
if (req->status != REQ_STATUS_FLSHD)
req->status = REQ_STATUS_RCVD;
spin_unlock_irqrestore(&c->lock, flags);
wake_up(req->wq);
P9_DPRINTK(P9_DEBUG_MUX, "wakeup: %d\n", req->tc->tag);
}
} }
EXPORT_SYMBOL(p9_client_cb); EXPORT_SYMBOL(p9_client_cb);
...@@ -486,9 +459,15 @@ static int p9_client_flush(struct p9_client *c, struct p9_req_t *oldreq) ...@@ -486,9 +459,15 @@ static int p9_client_flush(struct p9_client *c, struct p9_req_t *oldreq)
if (IS_ERR(req)) if (IS_ERR(req))
return PTR_ERR(req); return PTR_ERR(req);
req->flush_tag = oldtag;
/* we don't free anything here because RPC isn't complete */ /* if we haven't received a response for oldreq,
remove it from the list. */
spin_lock(&c->lock);
if (oldreq->status == REQ_STATUS_FLSH)
list_del(&oldreq->req_list);
spin_unlock(&c->lock);
p9_free_req(c, req);
return 0; return 0;
} }
...@@ -509,7 +488,6 @@ p9_client_rpc(struct p9_client *c, int8_t type, const char *fmt, ...) ...@@ -509,7 +488,6 @@ p9_client_rpc(struct p9_client *c, int8_t type, const char *fmt, ...)
struct p9_req_t *req; struct p9_req_t *req;
unsigned long flags; unsigned long flags;
int sigpending; int sigpending;
int flushed = 0;
P9_DPRINTK(P9_DEBUG_MUX, "client %p op %d\n", c, type); P9_DPRINTK(P9_DEBUG_MUX, "client %p op %d\n", c, type);
...@@ -546,42 +524,28 @@ p9_client_rpc(struct p9_client *c, int8_t type, const char *fmt, ...) ...@@ -546,42 +524,28 @@ p9_client_rpc(struct p9_client *c, int8_t type, const char *fmt, ...)
goto reterr; goto reterr;
} }
/* if it was a flush we just transmitted, return our tag */
if (type == P9_TFLUSH)
return req;
again:
P9_DPRINTK(P9_DEBUG_MUX, "wait %p tag: %d\n", req->wq, tag); P9_DPRINTK(P9_DEBUG_MUX, "wait %p tag: %d\n", req->wq, tag);
err = wait_event_interruptible(*req->wq, err = wait_event_interruptible(*req->wq,
req->status >= REQ_STATUS_RCVD); req->status >= REQ_STATUS_RCVD);
P9_DPRINTK(P9_DEBUG_MUX, "wait %p tag: %d returned %d (flushed=%d)\n", P9_DPRINTK(P9_DEBUG_MUX, "wait %p tag: %d returned %d\n",
req->wq, tag, err, flushed); req->wq, tag, err);
if (req->status == REQ_STATUS_ERROR) { if (req->status == REQ_STATUS_ERROR) {
P9_DPRINTK(P9_DEBUG_ERROR, "req_status error %d\n", req->t_err); P9_DPRINTK(P9_DEBUG_ERROR, "req_status error %d\n", req->t_err);
err = req->t_err; err = req->t_err;
} else if (err == -ERESTARTSYS && flushed) {
P9_DPRINTK(P9_DEBUG_MUX, "flushed - going again\n");
goto again;
} else if (req->status == REQ_STATUS_FLSHD) {
P9_DPRINTK(P9_DEBUG_MUX, "flushed - erestartsys\n");
err = -ERESTARTSYS;
} }
if ((err == -ERESTARTSYS) && (c->status == Connected) && (!flushed)) { if ((err == -ERESTARTSYS) && (c->status == Connected)) {
P9_DPRINTK(P9_DEBUG_MUX, "flushing\n"); P9_DPRINTK(P9_DEBUG_MUX, "flushing\n");
spin_lock_irqsave(&c->lock, flags);
if (req->status == REQ_STATUS_SENT)
req->status = REQ_STATUS_FLSH;
spin_unlock_irqrestore(&c->lock, flags);
sigpending = 1; sigpending = 1;
flushed = 1;
clear_thread_flag(TIF_SIGPENDING); clear_thread_flag(TIF_SIGPENDING);
if (c->trans_mod->cancel(c, req)) { if (c->trans_mod->cancel(c, req))
err = p9_client_flush(c, req); p9_client_flush(c, req);
if (err == 0)
goto again; /* if we received the response anyway, don't signal error */
} if (req->status == REQ_STATUS_RCVD)
err = 0;
} }
if (sigpending) { if (sigpending) {
...@@ -1244,19 +1208,53 @@ struct p9_wstat *p9_client_stat(struct p9_fid *fid) ...@@ -1244,19 +1208,53 @@ struct p9_wstat *p9_client_stat(struct p9_fid *fid)
ret->name, ret->uid, ret->gid, ret->muid, ret->extension, ret->name, ret->uid, ret->gid, ret->muid, ret->extension,
ret->n_uid, ret->n_gid, ret->n_muid); ret->n_uid, ret->n_gid, ret->n_muid);
p9_free_req(clnt, req);
return ret;
free_and_error: free_and_error:
p9_free_req(clnt, req); p9_free_req(clnt, req);
error: error:
return ret; kfree(ret);
return ERR_PTR(err);
} }
EXPORT_SYMBOL(p9_client_stat); EXPORT_SYMBOL(p9_client_stat);
static int p9_client_statsize(struct p9_wstat *wst, int optional)
{
int ret;
/* size[2] type[2] dev[4] qid[13] */
/* mode[4] atime[4] mtime[4] length[8]*/
/* name[s] uid[s] gid[s] muid[s] */
ret = 2+2+4+13+4+4+4+8+2+2+2+2;
if (wst->name)
ret += strlen(wst->name);
if (wst->uid)
ret += strlen(wst->uid);
if (wst->gid)
ret += strlen(wst->gid);
if (wst->muid)
ret += strlen(wst->muid);
if (optional) {
ret += 2+4+4+4; /* extension[s] n_uid[4] n_gid[4] n_muid[4] */
if (wst->extension)
ret += strlen(wst->extension);
}
return ret;
}
int p9_client_wstat(struct p9_fid *fid, struct p9_wstat *wst) int p9_client_wstat(struct p9_fid *fid, struct p9_wstat *wst)
{ {
int err; int err;
struct p9_req_t *req; struct p9_req_t *req;
struct p9_client *clnt; struct p9_client *clnt;
err = 0;
clnt = fid->clnt;
wst->size = p9_client_statsize(wst, clnt->dotu);
P9_DPRINTK(P9_DEBUG_9P, ">>> TWSTAT fid %d\n", fid->fid); P9_DPRINTK(P9_DEBUG_9P, ">>> TWSTAT fid %d\n", fid->fid);
P9_DPRINTK(P9_DEBUG_9P, P9_DPRINTK(P9_DEBUG_9P,
" sz=%x type=%x dev=%x qid=%x.%llx.%x\n" " sz=%x type=%x dev=%x qid=%x.%llx.%x\n"
...@@ -1268,10 +1266,8 @@ int p9_client_wstat(struct p9_fid *fid, struct p9_wstat *wst) ...@@ -1268,10 +1266,8 @@ int p9_client_wstat(struct p9_fid *fid, struct p9_wstat *wst)
wst->atime, wst->mtime, (unsigned long long)wst->length, wst->atime, wst->mtime, (unsigned long long)wst->length,
wst->name, wst->uid, wst->gid, wst->muid, wst->extension, wst->name, wst->uid, wst->gid, wst->muid, wst->extension,
wst->n_uid, wst->n_gid, wst->n_muid); wst->n_uid, wst->n_gid, wst->n_muid);
err = 0;
clnt = fid->clnt;
req = p9_client_rpc(clnt, P9_TWSTAT, "dwS", fid->fid, 0, wst); req = p9_client_rpc(clnt, P9_TWSTAT, "dwS", fid->fid, wst->size, wst);
if (IS_ERR(req)) { if (IS_ERR(req)) {
err = PTR_ERR(req); err = PTR_ERR(req);
goto error; goto error;
......
...@@ -213,8 +213,8 @@ static void p9_conn_cancel(struct p9_conn *m, int err) ...@@ -213,8 +213,8 @@ static void p9_conn_cancel(struct p9_conn *m, int err)
spin_unlock_irqrestore(&m->client->lock, flags); spin_unlock_irqrestore(&m->client->lock, flags);
list_for_each_entry_safe(req, rtmp, &cancel_list, req_list) { list_for_each_entry_safe(req, rtmp, &cancel_list, req_list) {
list_del(&req->req_list);
P9_DPRINTK(P9_DEBUG_ERROR, "call back req %p\n", req); P9_DPRINTK(P9_DEBUG_ERROR, "call back req %p\n", req);
list_del(&req->req_list);
p9_client_cb(m->client, req); p9_client_cb(m->client, req);
} }
} }
...@@ -336,7 +336,8 @@ static void p9_read_work(struct work_struct *work) ...@@ -336,7 +336,8 @@ static void p9_read_work(struct work_struct *work)
"mux %p pkt: size: %d bytes tag: %d\n", m, n, tag); "mux %p pkt: size: %d bytes tag: %d\n", m, n, tag);
m->req = p9_tag_lookup(m->client, tag); m->req = p9_tag_lookup(m->client, tag);
if (!m->req) { if (!m->req || (m->req->status != REQ_STATUS_SENT &&
m->req->status != REQ_STATUS_FLSH)) {
P9_DPRINTK(P9_DEBUG_ERROR, "Unexpected packet tag %d\n", P9_DPRINTK(P9_DEBUG_ERROR, "Unexpected packet tag %d\n",
tag); tag);
err = -EIO; err = -EIO;
...@@ -361,10 +362,11 @@ static void p9_read_work(struct work_struct *work) ...@@ -361,10 +362,11 @@ static void p9_read_work(struct work_struct *work)
if ((m->req) && (m->rpos == m->rsize)) { /* packet is read in */ if ((m->req) && (m->rpos == m->rsize)) { /* packet is read in */
P9_DPRINTK(P9_DEBUG_TRANS, "got new packet\n"); P9_DPRINTK(P9_DEBUG_TRANS, "got new packet\n");
spin_lock(&m->client->lock); spin_lock(&m->client->lock);
if (m->req->status != REQ_STATUS_ERROR)
m->req->status = REQ_STATUS_RCVD;
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); p9_client_cb(m->client, m->req);
m->rbuf = NULL; m->rbuf = NULL;
m->rpos = 0; m->rpos = 0;
m->rsize = 0; m->rsize = 0;
...@@ -454,6 +456,7 @@ static void p9_write_work(struct work_struct *work) ...@@ -454,6 +456,7 @@ static void p9_write_work(struct work_struct *work)
req = list_entry(m->unsent_req_list.next, struct p9_req_t, req = list_entry(m->unsent_req_list.next, struct p9_req_t,
req_list); req_list);
req->status = REQ_STATUS_SENT; req->status = REQ_STATUS_SENT;
P9_DPRINTK(P9_DEBUG_TRANS, "move req %p\n", req);
list_move_tail(&req->req_list, &m->req_list); list_move_tail(&req->req_list, &m->req_list);
m->wbuf = req->tc->sdata; m->wbuf = req->tc->sdata;
...@@ -683,12 +686,13 @@ static int p9_fd_cancel(struct p9_client *client, struct p9_req_t *req) ...@@ -683,12 +686,13 @@ static int p9_fd_cancel(struct p9_client *client, struct p9_req_t *req)
P9_DPRINTK(P9_DEBUG_TRANS, "client %p req %p\n", client, req); P9_DPRINTK(P9_DEBUG_TRANS, "client %p req %p\n", client, req);
spin_lock(&client->lock); spin_lock(&client->lock);
list_del(&req->req_list);
if (req->status == REQ_STATUS_UNSENT) { if (req->status == REQ_STATUS_UNSENT) {
list_del(&req->req_list);
req->status = REQ_STATUS_FLSHD; req->status = REQ_STATUS_FLSHD;
ret = 0; ret = 0;
} } else if (req->status == REQ_STATUS_SENT)
req->status = REQ_STATUS_FLSH;
spin_unlock(&client->lock); spin_unlock(&client->lock);
......
...@@ -295,6 +295,7 @@ handle_recv(struct p9_client *client, struct p9_trans_rdma *rdma, ...@@ -295,6 +295,7 @@ handle_recv(struct p9_client *client, struct p9_trans_rdma *rdma,
goto err_out; goto err_out;
req->rc = c->rc; req->rc = c->rc;
req->status = REQ_STATUS_RCVD;
p9_client_cb(client, req); p9_client_cb(client, req);
return; return;
......
...@@ -134,6 +134,7 @@ static void req_done(struct virtqueue *vq) ...@@ -134,6 +134,7 @@ static void req_done(struct virtqueue *vq)
P9_DPRINTK(P9_DEBUG_TRANS, ": rc %p\n", rc); P9_DPRINTK(P9_DEBUG_TRANS, ": rc %p\n", rc);
P9_DPRINTK(P9_DEBUG_TRANS, ": lookup tag %d\n", rc->tag); P9_DPRINTK(P9_DEBUG_TRANS, ": lookup tag %d\n", rc->tag);
req = p9_tag_lookup(chan->client, rc->tag); req = p9_tag_lookup(chan->client, rc->tag);
req->status = REQ_STATUS_RCVD;
p9_client_cb(chan->client, req); p9_client_cb(chan->client, req);
} }
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment