static void p9_xosclient_rerror(struct p9_req_t *req) { struct p9_fcall *rcall; u16 tag; struct p9_xos_device *dev = (struct p9_xos_device *)req->aux; struct p9_xos_endpoint *ep = &dev->driver->ep[RD_EP]; unsigned long flags; if (p9_parse_header(req->tc, &req->tc->size, &req->tc->id, &tag, 1)) warning("Failed to decode header !"); kfree(req->tc); spin_lock_irqsave(&dev->driver->ep_lock, flags); p9_xos_deque_push(ep->rqueue, a2n(req->tc->sdata - 8, ep), ep); nb_free_packets++; spin_unlock_irqrestore(&dev->driver->ep_lock, flags); rcall = kmalloc(sizeof(struct p9_fcall) + 32, GFP_KERNEL); p9pdu_reset(rcall); rcall->sdata = (u8 *) (rcall + sizeof(struct p9_fcall)); p9pdu_writef(rcall, 0, "dbwT", 0, P9_RERROR, tag, "9P destination service closed"); p9pdu_finalize(rcall); req->rc = rcall; req->tc = NULL; spin_lock(&dev->lock); dev->ack_count += 1; spin_unlock(&dev->lock); p9_xos_add_write_request(req, 0); }
int p9pdu_finalize(struct p9_client *clnt, struct p9_fcall *pdu) { int size = pdu->size; int err; pdu->size = 0; err = p9pdu_writef(pdu, 0, "d", size); pdu->size = size; trace_9p_protocol_dump(clnt, pdu); p9_debug(P9_DEBUG_9P, ">>> size=%d type: %d tag: %d\n", pdu->size, pdu->id, pdu->tag); return err; }
int p9pdu_finalize(struct p9_fcall *pdu) { int size = pdu->size; int err; pdu->size = 0; err = p9pdu_writef(pdu, 0, "d", size); pdu->size = size; #ifdef CONFIG_NET_9P_DEBUG if ((p9_debug_level & P9_DEBUG_PKT) == P9_DEBUG_PKT) p9pdu_dump(0, pdu); #endif P9_DPRINTK(P9_DEBUG_9P, ">>> size=%d type: %d tag: %d\n", pdu->size, pdu->id, pdu->tag); return err; }
int p9pdu_prepare(struct p9_fcall *pdu, int16_t tag, int8_t type) { return p9pdu_writef(pdu, 0, "dbw", 0, type, tag); }
int p9pdu_vwritef(struct p9_fcall *pdu, int proto_version, const char *fmt, va_list ap) { const char *ptr; int errcode = 0; for (ptr = fmt; *ptr; ptr++) { switch (*ptr) { case 'b': { int8_t val = va_arg(ap, int); if (pdu_write(pdu, &val, sizeof(val))) errcode = -EFAULT; } break; case 'w': { __le16 val = cpu_to_le16(va_arg(ap, int)); if (pdu_write(pdu, &val, sizeof(val))) errcode = -EFAULT; } break; case 'd': { __le32 val = cpu_to_le32(va_arg(ap, int32_t)); if (pdu_write(pdu, &val, sizeof(val))) errcode = -EFAULT; } break; case 'q': { __le64 val = cpu_to_le64(va_arg(ap, int64_t)); if (pdu_write(pdu, &val, sizeof(val))) errcode = -EFAULT; } break; case 's': { const char *sptr = va_arg(ap, const char *); int16_t len = 0; if (sptr) len = MIN(strlen(sptr), USHRT_MAX); errcode = p9pdu_writef(pdu, proto_version, "w", len); if (!errcode && pdu_write(pdu, sptr, len)) errcode = -EFAULT; } break; case 'Q': { const struct p9_qid *qid = va_arg(ap, const struct p9_qid *); errcode = p9pdu_writef(pdu, proto_version, "bdq", qid->type, qid->version, qid->path); } break; case 'S': { const struct p9_wstat *stbuf = va_arg(ap, const struct p9_wstat *); errcode = p9pdu_writef(pdu, proto_version, "wwdQdddqssss?sddd", stbuf->size, stbuf->type, stbuf->dev, &stbuf->qid, stbuf->mode, stbuf->atime, stbuf->mtime, stbuf->length, stbuf->name, stbuf->uid, stbuf->gid, stbuf->muid, stbuf->extension, stbuf->n_uid, stbuf->n_gid, stbuf->n_muid); } break; case 'D': { int32_t count = va_arg(ap, int32_t); const void *data = va_arg(ap, const void *); errcode = p9pdu_writef(pdu, proto_version, "d", count); if (!errcode && pdu_write(pdu, data, count)) errcode = -EFAULT; } break; case 'U': { int32_t count = va_arg(ap, int32_t); const char __user *udata = va_arg(ap, const void __user *); errcode = p9pdu_writef(pdu, proto_version, "d", count); if (!errcode && pdu_write_u(pdu, udata, count)) errcode = -EFAULT; } break; case 'T': { int16_t nwname = va_arg(ap, int); const char **wnames = va_arg(ap, const char **); errcode = p9pdu_writef(pdu, proto_version, "w", nwname); if (!errcode) { int i; for (i = 0; i < nwname; i++) { errcode = p9pdu_writef(pdu, proto_version, "s", wnames[i]); if (errcode) break; } } } break; case 'R': { int16_t nwqid = va_arg(ap, int); struct p9_qid *wqids = va_arg(ap, struct p9_qid *); errcode = p9pdu_writef(pdu, proto_version, "w", nwqid); if (!errcode) { int i; for (i = 0; i < nwqid; i++) { errcode = p9pdu_writef(pdu, proto_version, "Q", &wqids[i]); if (errcode) break; } } } break; case '?': if ((proto_version != p9_proto_2000u) && (proto_version != p9_proto_2000L)) return 0; break; default: BUG(); break; } if (errcode) break; } return errcode; }