Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 0488713c authored by Linus Torvalds's avatar Linus Torvalds
Browse files
* '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
Loading
Loading
Loading
Loading
+0 −1
Original line number Diff line number Diff line
@@ -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;
+55 −59
Original line number Diff line number Diff line
@@ -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,36 +323,10 @@ 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);
}
}
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)) {
	if ((err == -ERESTARTSYS) && (c->status == Connected)) {
		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;
		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) {
@@ -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->n_uid, ret->n_gid, ret->n_muid);

	p9_free_req(clnt, req);
	return ret;

free_and_error:
	p9_free_req(clnt, req);
error:
	return ret;
	kfree(ret);
	return ERR_PTR(err);
}
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 err;
	struct p9_req_t *req;
	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,
		"     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)
		wst->atime, wst->mtime, (unsigned long long)wst->length,
		wst->name, wst->uid, wst->gid, wst->muid, wst->extension,
		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)) {
		err = PTR_ERR(req);
		goto error;
+9 −5
Original line number Diff line number Diff line
@@ -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);

+1 −0
Original line number Diff line number Diff line
@@ -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;
+1 −0
Original line number Diff line number Diff line
@@ -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);
	}
}