#include <linux/module.h>
#include <linux/errno.h>
#include <linux/uaccess.h>
+#include <linux/sched.h>
+#include <linux/types.h>
#include <net/9p/9p.h>
#include <net/9p/client.h>
#include "protocol.h"
#endif
static int
-p9pdu_writef(struct p9_fcall *pdu, int optional, const char *fmt, ...);
-
-#define PACKET_DEBUG 0
+p9pdu_writef(struct p9_fcall *pdu, int proto_version, const char *fmt, ...);
+#ifdef CONFIG_NET_9P_DEBUG
void
p9pdu_dump(int way, struct p9_fcall *pdu)
{
n += scnprintf(buf + n, buflen - n, "\n");
if (way)
- printk(KERN_NOTICE "[[(%d)[ %s\n", datalen, buf);
+ P9_DPRINTK(P9_DEBUG_PKT, "[[[(%d) %s\n", datalen, buf);
else
- printk(KERN_NOTICE "]](%d)] %s\n", datalen, buf);
+ P9_DPRINTK(P9_DEBUG_PKT, "]]](%d) %s\n", datalen, buf);
}
+#else
+void
+p9pdu_dump(int way, struct p9_fcall *pdu)
+{
+}
+#endif
EXPORT_SYMBOL(p9pdu_dump);
void p9stat_free(struct p9_wstat *stbuf)
*/
static int
-p9pdu_vreadf(struct p9_fcall *pdu, int optional, const char *fmt, va_list ap)
+p9pdu_vreadf(struct p9_fcall *pdu, int proto_version, const char *fmt,
+ va_list ap)
{
const char *ptr;
int errcode = 0;
break;
case 'w':{
int16_t *val = va_arg(ap, int16_t *);
- if (pdu_read(pdu, val, sizeof(*val))) {
+ __le16 le_val;
+ if (pdu_read(pdu, &le_val, sizeof(le_val))) {
errcode = -EFAULT;
break;
}
- *val = cpu_to_le16(*val);
+ *val = le16_to_cpu(le_val);
}
break;
case 'd':{
int32_t *val = va_arg(ap, int32_t *);
- if (pdu_read(pdu, val, sizeof(*val))) {
+ __le32 le_val;
+ if (pdu_read(pdu, &le_val, sizeof(le_val))) {
errcode = -EFAULT;
break;
}
- *val = cpu_to_le32(*val);
+ *val = le32_to_cpu(le_val);
}
break;
case 'q':{
int64_t *val = va_arg(ap, int64_t *);
- if (pdu_read(pdu, val, sizeof(*val))) {
+ __le64 le_val;
+ if (pdu_read(pdu, &le_val, sizeof(le_val))) {
errcode = -EFAULT;
break;
}
- *val = cpu_to_le64(*val);
+ *val = le64_to_cpu(le_val);
}
break;
case 's':{
- char **ptr = va_arg(ap, char **);
+ char **sptr = va_arg(ap, char **);
int16_t len;
int size;
- errcode = p9pdu_readf(pdu, optional, "w", &len);
+ errcode = p9pdu_readf(pdu, proto_version,
+ "w", &len);
if (errcode)
break;
size = MAX(len, 0);
- *ptr = kmalloc(size + 1, GFP_KERNEL);
- if (*ptr == NULL) {
+ *sptr = kmalloc(size + 1, GFP_KERNEL);
+ if (*sptr == NULL) {
errcode = -EFAULT;
break;
}
- if (pdu_read(pdu, *ptr, size)) {
+ if (pdu_read(pdu, *sptr, size)) {
errcode = -EFAULT;
- kfree(*ptr);
- *ptr = NULL;
+ kfree(*sptr);
+ *sptr = NULL;
} else
- (*ptr)[size] = 0;
+ (*sptr)[size] = 0;
}
break;
case 'Q':{
struct p9_qid *qid =
va_arg(ap, struct p9_qid *);
- errcode = p9pdu_readf(pdu, optional, "bdq",
+ errcode = p9pdu_readf(pdu, proto_version, "bdq",
&qid->type, &qid->version,
&qid->path);
}
struct p9_wstat *stbuf =
va_arg(ap, struct p9_wstat *);
- stbuf->extension = NULL;
+ memset(stbuf, 0, sizeof(struct p9_wstat));
stbuf->n_uid = stbuf->n_gid = stbuf->n_muid =
- -1;
+ -1;
errcode =
- p9pdu_readf(pdu, optional,
+ p9pdu_readf(pdu, proto_version,
"wwdQdddqssss?sddd",
&stbuf->size, &stbuf->type,
&stbuf->dev, &stbuf->qid,
void **data = va_arg(ap, void **);
errcode =
- p9pdu_readf(pdu, optional, "d", count);
+ p9pdu_readf(pdu, proto_version, "d", count);
if (!errcode) {
*count =
MIN(*count,
int16_t *nwname = va_arg(ap, int16_t *);
char ***wnames = va_arg(ap, char ***);
- errcode =
- p9pdu_readf(pdu, optional, "w", nwname);
+ errcode = p9pdu_readf(pdu, proto_version,
+ "w", nwname);
if (!errcode) {
*wnames =
kmalloc(sizeof(char *) * *nwname,
for (i = 0; i < *nwname; i++) {
errcode =
- p9pdu_readf(pdu, optional,
+ p9pdu_readf(pdu,
+ proto_version,
"s",
&(*wnames)[i]);
if (errcode)
*wqids = NULL;
errcode =
- p9pdu_readf(pdu, optional, "w", nwqid);
+ p9pdu_readf(pdu, proto_version, "w", nwqid);
if (!errcode) {
*wqids =
kmalloc(*nwqid *
for (i = 0; i < *nwqid; i++) {
errcode =
- p9pdu_readf(pdu, optional,
+ p9pdu_readf(pdu,
+ proto_version,
"Q",
&(*wqids)[i]);
if (errcode)
}
break;
case '?':
- if (!optional)
+ if (proto_version != p9_proto_2000u)
return 0;
break;
default:
}
int
-p9pdu_vwritef(struct p9_fcall *pdu, int optional, const char *fmt, va_list ap)
+p9pdu_vwritef(struct p9_fcall *pdu, int proto_version, const char *fmt,
+ va_list ap)
{
const char *ptr;
int errcode = 0;
}
break;
case 'w':{
- int16_t val = va_arg(ap, int);
+ __le16 val = cpu_to_le16(va_arg(ap, int));
if (pdu_write(pdu, &val, sizeof(val)))
errcode = -EFAULT;
}
break;
case 'd':{
- int32_t val = va_arg(ap, int32_t);
+ __le32 val = cpu_to_le32(va_arg(ap, int32_t));
if (pdu_write(pdu, &val, sizeof(val)))
errcode = -EFAULT;
}
break;
case 'q':{
- int64_t val = va_arg(ap, int64_t);
+ __le64 val = cpu_to_le64(va_arg(ap, int64_t));
if (pdu_write(pdu, &val, sizeof(val)))
errcode = -EFAULT;
}
break;
case 's':{
- const char *ptr = va_arg(ap, const char *);
+ const char *sptr = va_arg(ap, const char *);
int16_t len = 0;
- if (ptr)
- len = MIN(strlen(ptr), USHORT_MAX);
+ if (sptr)
+ len = MIN(strlen(sptr), USHORT_MAX);
- errcode = p9pdu_writef(pdu, optional, "w", len);
- if (!errcode && pdu_write(pdu, ptr, len))
+ errcode = p9pdu_writef(pdu, proto_version,
+ "w", len);
+ if (!errcode && pdu_write(pdu, sptr, len))
errcode = -EFAULT;
}
break;
const struct p9_qid *qid =
va_arg(ap, const struct p9_qid *);
errcode =
- p9pdu_writef(pdu, optional, "bdq",
+ p9pdu_writef(pdu, proto_version, "bdq",
qid->type, qid->version,
qid->path);
} break;
const struct p9_wstat *stbuf =
va_arg(ap, const struct p9_wstat *);
errcode =
- p9pdu_writef(pdu, optional,
+ p9pdu_writef(pdu, proto_version,
"wwdQdddqssss?sddd",
stbuf->size, stbuf->type,
stbuf->dev, &stbuf->qid,
int32_t count = va_arg(ap, int32_t);
const void *data = va_arg(ap, const void *);
- errcode =
- p9pdu_writef(pdu, optional, "d", count);
+ errcode = p9pdu_writef(pdu, proto_version, "d",
+ count);
if (!errcode && pdu_write(pdu, data, count))
errcode = -EFAULT;
}
case 'U':{
int32_t count = va_arg(ap, int32_t);
const char __user *udata =
- va_arg(ap, const void *);
- errcode =
- p9pdu_writef(pdu, optional, "d", count);
+ va_arg(ap, const void __user *);
+ errcode = p9pdu_writef(pdu, proto_version, "d",
+ count);
if (!errcode && pdu_write_u(pdu, udata, count))
errcode = -EFAULT;
}
int16_t nwname = va_arg(ap, int);
const char **wnames = va_arg(ap, const char **);
- errcode =
- p9pdu_writef(pdu, optional, "w", nwname);
+ errcode = p9pdu_writef(pdu, proto_version, "w",
+ nwname);
if (!errcode) {
int i;
for (i = 0; i < nwname; i++) {
errcode =
- p9pdu_writef(pdu, optional,
+ p9pdu_writef(pdu,
+ proto_version,
"s",
wnames[i]);
if (errcode)
struct p9_qid *wqids =
va_arg(ap, struct p9_qid *);
- errcode =
- p9pdu_writef(pdu, optional, "w", nwqid);
+ errcode = p9pdu_writef(pdu, proto_version, "w",
+ nwqid);
if (!errcode) {
int i;
for (i = 0; i < nwqid; i++) {
errcode =
- p9pdu_writef(pdu, optional,
+ p9pdu_writef(pdu,
+ proto_version,
"Q",
&wqids[i]);
if (errcode)
}
break;
case '?':
- if (!optional)
+ if (proto_version != p9_proto_2000u)
return 0;
break;
default:
return errcode;
}
-int p9pdu_readf(struct p9_fcall *pdu, int optional, const char *fmt, ...)
+int p9pdu_readf(struct p9_fcall *pdu, int proto_version, const char *fmt, ...)
{
va_list ap;
int ret;
va_start(ap, fmt);
- ret = p9pdu_vreadf(pdu, optional, fmt, ap);
+ ret = p9pdu_vreadf(pdu, proto_version, fmt, ap);
va_end(ap);
return ret;
}
static int
-p9pdu_writef(struct p9_fcall *pdu, int optional, const char *fmt, ...)
+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, optional, fmt, ap);
+ ret = p9pdu_vwritef(pdu, proto_version, fmt, ap);
va_end(ap);
return ret;
}
+int p9stat_read(char *buf, int len, struct p9_wstat *st, int proto_version)
+{
+ struct p9_fcall fake_pdu;
+ int ret;
+
+ fake_pdu.size = len;
+ fake_pdu.capacity = len;
+ fake_pdu.sdata = buf;
+ fake_pdu.offset = 0;
+
+ ret = p9pdu_readf(&fake_pdu, proto_version, "S", st);
+ if (ret) {
+ P9_DPRINTK(P9_DEBUG_9P, "<<< p9stat_read failed: %d\n", ret);
+ p9pdu_dump(1, &fake_pdu);
+ }
+
+ return ret;
+}
+EXPORT_SYMBOL(p9stat_read);
+
int p9pdu_prepare(struct p9_fcall *pdu, int16_t tag, int8_t type)
{
return p9pdu_writef(pdu, 0, "dbw", 0, type, tag);
err = p9pdu_writef(pdu, 0, "d", size);
pdu->size = size;
- if (PACKET_DEBUG)
+#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;
}