static struct p9_fid *p9_fid_create(struct p9_client *clnt) { int err; struct p9_fid *fid; P9_DPRINTK(P9_DEBUG_FID, "clnt %p\n", clnt); fid = kmalloc(sizeof(struct p9_fid), GFP_KERNEL); if (!fid) return ERR_PTR(-ENOMEM); fid->fid = p9_idpool_get(clnt->fidpool); if (fid->fid < 0) { err = -ENOSPC; goto error; } memset(&fid->qid, 0, sizeof(struct p9_qid)); fid->mode = -1; fid->rdir_fpos = 0; fid->uid = current->fsuid; fid->clnt = clnt; fid->aux = NULL; spin_lock(&clnt->lock); list_add(&fid->flist, &clnt->fidlist); spin_unlock(&clnt->lock); return fid; error: kfree(fid); return ERR_PTR(err); }
static struct p9_fid *p9_fid_create(struct p9_client *clnt) { int ret; struct p9_fid *fid; unsigned long flags; P9_DPRINTK(P9_DEBUG_FID, "clnt %p\n", clnt); fid = kmalloc(sizeof(struct p9_fid), GFP_KERNEL); if (!fid) return ERR_PTR(-ENOMEM); ret = p9_idpool_get(clnt->fidpool); if (ret < 0) { ret = -ENOSPC; goto error; } fid->fid = ret; memset(&fid->qid, 0, sizeof(struct p9_qid)); fid->mode = -1; fid->rdir_fpos = 0; fid->uid = current_fsuid(); fid->clnt = clnt; fid->aux = NULL; spin_lock_irqsave(&clnt->lock, flags); list_add(&fid->flist, &clnt->fidlist); spin_unlock_irqrestore(&clnt->lock, flags); return fid; error: kfree(fid); return ERR_PTR(ret); }
static int p9_tag_init(struct p9_client *c) { int err = 0; c->tagpool = p9_idpool_create(); if (IS_ERR(c->tagpool)) { err = PTR_ERR(c->tagpool); c->tagpool = NULL; goto error; } p9_idpool_get(c->tagpool); /* reserve tag 0 */ c->max_tag = 0; error: return err; }
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); }