static int p9pdu_writef(struct p9_fcall *pdu, int proto_version, const char *fmt, ...) { va_list ap; int ret; va_start(ap, fmt); ret = p9pdu_vwritef(pdu, proto_version, fmt, ap); va_end(ap); return ret; }
static struct p9_req_t * p9_client_rpc(struct p9_client *c, int8_t type, const char *fmt, ...) { va_list ap; int tag, err; 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); if (c->status != Connected) return ERR_PTR(-EIO); if (signal_pending(current)) { sigpending = 1; clear_thread_flag(TIF_SIGPENDING); } else sigpending = 0; tag = P9_NOTAG; if (type != P9_TVERSION) { tag = p9_idpool_get(c->tagpool); if (tag < 0) return ERR_PTR(-ENOMEM); } req = p9_tag_alloc(c, tag); if (IS_ERR(req)) return req; /* marshall the data */ p9pdu_prepare(req->tc, tag, type); va_start(ap, fmt); err = p9pdu_vwritef(req->tc, c->dotu, fmt, ap); va_end(ap); p9pdu_finalize(req->tc); err = c->trans_mod->request(c, req); if (err < 0) { c->status = Disconnected; 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); 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); 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 (sigpending) { spin_lock_irqsave(¤t->sighand->siglock, flags); recalc_sigpending(); spin_unlock_irqrestore(¤t->sighand->siglock, flags); } if (err < 0) goto reterr; err = p9_check_errors(c, req); if (!err) { P9_DPRINTK(P9_DEBUG_MUX, "exit: client %p op %d\n", c, type); return req; } reterr: P9_DPRINTK(P9_DEBUG_MUX, "exit: client %p op %d error: %d\n", c, type, err); p9_free_req(c, req); return ERR_PTR(err); }