Return-Path: Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1758470AbZDEVjU (ORCPT ); Sun, 5 Apr 2009 17:39:20 -0400 Received: (majordomo@vger.kernel.org) by vger.kernel.org id S1753644AbZDEVjJ (ORCPT ); Sun, 5 Apr 2009 17:39:09 -0400 Received: from yw-out-2324.google.com ([74.125.46.31]:63578 "EHLO yw-out-2324.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1753492AbZDEVjG convert rfc822-to-8bit (ORCPT ); Sun, 5 Apr 2009 17:39:06 -0400 DomainKey-Signature: a=rsa-sha1; c=nofws; d=gmail.com; s=gamma; h=mime-version:in-reply-to:references:date:message-id:subject:from:to :cc:content-type:content-transfer-encoding; b=TvH2YvIW8RtsVOvE2+qxMmJJskgEzPlRBU7+HipqiDxmux0L/sSEP6J/+SXzN2kMM4 7MKDTJ+gfBD48gSz5fBgs0q+gmPOgdDVArF7ZuMrLS/8Q+DbVPfOslJUwMSMh6ELbGUi SFoStdTrZfWXdMJp0DDEDGT8rhtolc+m0S9hc= MIME-Version: 1.0 In-Reply-To: <20090402233707.GB7842@mallorn> References: <20090402233707.GB7842@mallorn> Date: Sun, 5 Apr 2009 16:38:54 -0500 Message-ID: Subject: Re: [V9fs-developer] [PATCH] net/9p: handle correctly interrupted 9P requests From: Eric Van Hensbergen To: Latchesar Ionkov Cc: v9fs-developer@lists.sourceforge.net, linux-kernel@vger.kernel.org Content-Type: text/plain; charset=ISO-8859-1 Content-Transfer-Encoding: 8BIT Sender: linux-kernel-owner@vger.kernel.org List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Content-Length: 10524 Lines: 255 Applied with some minor style changes to v9fs-devel. David Miller has requested that all patches to the net tree be cc:'d to netdev@vger.kernel.org. The other patches you sent have been applied as well. -eric On Thu, Apr 2, 2009 at 6:37 PM, Latchesar Ionkov wrote: > Currently the 9p code crashes when a operation is interrupted, i.e. for > example when the user presses ^C while reading from a file. > > This patch fixes the code that is responsible for interruption and flushing > of 9P operations. > > Signed-off-by: Latchesar Ionkov > > diff --git a/include/net/9p/client.h b/include/net/9p/client.h > index 4012e07..e268122 100644 > --- a/include/net/9p/client.h > +++ b/include/net/9p/client.h > @@ -98,7 +98,6 @@ enum p9_req_status_t { > ?struct p9_req_t { > ? ? ? ?int status; > ? ? ? ?int t_err; > - ? ? ? u16 flush_tag; > ? ? ? ?wait_queue_head_t *wq; > ? ? ? ?struct p9_fcall *tc; > ? ? ? ?struct p9_fcall *rc; > diff --git a/net/9p/client.c b/net/9p/client.c > index c079df6..f5634b5 100644 > --- a/net/9p/client.c > +++ b/net/9p/client.c > @@ -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->rc); > > - ? ? ? req->flush_tag = 0; > ? ? ? ?req->tc->tag = tag-1; > ? ? ? ?req->status = REQ_STATUS_ALLOC; > > @@ -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) > ?{ > - ? ? ? struct p9_req_t *other_req; > - ? ? ? unsigned long flags; > - > ? ? ? ?P9_DPRINTK(P9_DEBUG_MUX, " tag %d\n", req->tc->tag); > - > - ? ? ? if (req->status == REQ_STATUS_ERROR) > - ? ? ? ? ? ? ? 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); > - ? ? ? } > + ? ? ? wake_up(req->wq); > + ? ? ? P9_DPRINTK(P9_DEBUG_MUX, "wakeup: %d\n", req->tc->tag); > ?} > ?EXPORT_SYMBOL(p9_client_cb); > > @@ -486,9 +459,15 @@ static int p9_client_flush(struct p9_client *c, struct p9_req_t *oldreq) > ? ? ? ?if (IS_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; > ?} > > @@ -509,7 +488,6 @@ p9_client_rpc(struct p9_client *c, int8_t type, const char *fmt, ...) > ? ? ? ?struct p9_req_t *req; > ? ? ? ?unsigned long flags; > ? ? ? ?int sigpending; > - ? ? ? int flushed = 0; > > ? ? ? ?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, ...) > ? ? ? ? ? ? ? ?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); > ? ? ? ?err = wait_event_interruptible(*req->wq, > ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?req->status >= REQ_STATUS_RCVD); > - ? ? ? P9_DPRINTK(P9_DEBUG_MUX, "wait %p tag: %d returned %d (flushed=%d)\n", > - ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? req->wq, tag, err, flushed); > + ? ? ? P9_DPRINTK(P9_DEBUG_MUX, "wait %p tag: %d returned %d\n", > + ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? req->wq, tag, err); > > ? ? ? ?if (req->status == REQ_STATUS_ERROR) { > ? ? ? ? ? ? ? ?P9_DPRINTK(P9_DEBUG_ERROR, "req_status error %d\n", 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)) { > - ? ? ? ? ? ? ? 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); > + ? ? ? if ((err == -ERESTARTSYS) && (c->status == Connected)) { > + ? ? ? ? ? ? ? P9_DPRINTK(P9_DEBUG_MUX, "flushing\n"); > ? ? ? ? ? ? ? ?sigpending = 1; > - ? ? ? ? ? ? ? flushed = 1; > ? ? ? ? ? ? ? ?clear_thread_flag(TIF_SIGPENDING); > > - ? ? ? ? ? ? ? if (c->trans_mod->cancel(c, req)) { > - ? ? ? ? ? ? ? ? ? ? ? err = p9_client_flush(c, req); > - ? ? ? ? ? ? ? ? ? ? ? if (err == 0) > - ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? goto again; > - ? ? ? ? ? ? ? } > + ? ? ? ? ? ? ? if (c->trans_mod->cancel(c, req)) > + ? ? ? ? ? ? ? ? ? ? ? p9_client_flush(c, req); > + > + ? ? ? ? ? ? ? /* if we received the response anyway, don't signal error */ > + ? ? ? ? ? ? ? if (req->status == REQ_STATUS_RCVD) > + ? ? ? ? ? ? ? ? ? ? ? err = 0; > ? ? ? ?} > > ? ? ? ?if (sigpending) { > diff --git a/net/9p/trans_fd.c b/net/9p/trans_fd.c > index c613ed0..a2a1814 100644 > --- a/net/9p/trans_fd.c > +++ b/net/9p/trans_fd.c > @@ -213,8 +213,8 @@ static void p9_conn_cancel(struct p9_conn *m, int err) > ? ? ? ?spin_unlock_irqrestore(&m->client->lock, flags); > > ? ? ? ?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); > + ? ? ? ? ? ? ? list_del(&req->req_list); > ? ? ? ? ? ? ? ?p9_client_cb(m->client, req); > ? ? ? ?} > ?} > @@ -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); > > ? ? ? ? ? ? ? ?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", > ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? tag); > ? ? ? ? ? ? ? ? ? ? ? ?err = -EIO; > @@ -361,10 +362,11 @@ static void p9_read_work(struct work_struct *work) > ? ? ? ?if ((m->req) && (m->rpos == m->rsize)) { /* packet is read in */ > ? ? ? ? ? ? ? ?P9_DPRINTK(P9_DEBUG_TRANS, "got new packet\n"); > ? ? ? ? ? ? ? ?spin_lock(&m->client->lock); > + ? ? ? ? ? ? ? if (m->req->status != REQ_STATUS_ERROR) > + ? ? ? ? ? ? ? ? ? ? ? m->req->status = REQ_STATUS_RCVD; > ? ? ? ? ? ? ? ?list_del(&m->req->req_list); > ? ? ? ? ? ? ? ?spin_unlock(&m->client->lock); > ? ? ? ? ? ? ? ?p9_client_cb(m->client, m->req); > - > ? ? ? ? ? ? ? ?m->rbuf = NULL; > ? ? ? ? ? ? ? ?m->rpos = 0; > ? ? ? ? ? ? ? ?m->rsize = 0; > @@ -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); > ? ? ? ? ? ? ? ?req->status = REQ_STATUS_SENT; > + ? ? ? ? ? ? ? P9_DPRINTK(P9_DEBUG_TRANS, "move req %p\n", req); > ? ? ? ? ? ? ? ?list_move_tail(&req->req_list, &m->req_list); > > ? ? ? ? ? ? ? ?m->wbuf = req->tc->sdata; > @@ -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); > > ? ? ? ?spin_lock(&client->lock); > - ? ? ? list_del(&req->req_list); > > ? ? ? ?if (req->status == REQ_STATUS_UNSENT) { > + ? ? ? ? ? ? ? list_del(&req->req_list); > ? ? ? ? ? ? ? ?req->status = REQ_STATUS_FLSHD; > ? ? ? ? ? ? ? ?ret = 0; > - ? ? ? } > + ? ? ? } else if (req->status == REQ_STATUS_SENT) > + ? ? ? ? ? ? ? req->status = REQ_STATUS_FLSH; > > ? ? ? ?spin_unlock(&client->lock); > > diff --git a/net/9p/trans_rdma.c b/net/9p/trans_rdma.c > index 7fa0eb2..ac49900 100644 > --- a/net/9p/trans_rdma.c > +++ b/net/9p/trans_rdma.c > @@ -295,6 +295,7 @@ handle_recv(struct p9_client *client, struct p9_trans_rdma *rdma, > ? ? ? ? ? ? ? ?goto err_out; > > ? ? ? ?req->rc = c->rc; > + ? ? ? req->status = REQ_STATUS_RCVD; > ? ? ? ?p9_client_cb(client, req); > > ? ? ? ?return; > diff --git a/net/9p/trans_virtio.c b/net/9p/trans_virtio.c > index 2d7781e..bb8579a 100644 > --- a/net/9p/trans_virtio.c > +++ b/net/9p/trans_virtio.c > @@ -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, ": lookup tag %d\n", rc->tag); > ? ? ? ? ? ? ? ?req = p9_tag_lookup(chan->client, rc->tag); > + ? ? ? ? ? ? ? req->status = REQ_STATUS_RCVD; > ? ? ? ? ? ? ? ?p9_client_cb(chan->client, req); > ? ? ? ?} > ?} > > ------------------------------------------------------------------------------ > _______________________________________________ > V9fs-developer mailing list > V9fs-developer@lists.sourceforge.net > https://lists.sourceforge.net/lists/listinfo/v9fs-developer > -- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/