Revision 405a549a

b/hw/virtio-9p-debug.h
1
#ifndef _QEMU_VIRTIO_9P_DEBUG_H
2
#define _QEMU_VIRTIO_9P_DEBUG_H
3

  
4
extern int dotu;
5
void pprint_pdu(V9fsPDU *pdu);
6

  
7
#endif
b/hw/virtio-9p.c
71 71
    return copied;
72 72
}
73 73

  
74
static size_t pdu_unpack(void *dst, V9fsPDU *pdu, size_t offset, size_t size)
75
{
76
    return pdu_packunpack(dst, pdu->elem.out_sg, pdu->elem.out_num,
77
                         offset, size, 0);
78
}
79

  
80
static size_t pdu_pack(V9fsPDU *pdu, size_t offset, const void *src,
81
                        size_t size)
82
{
83
    return pdu_packunpack((void *)src, pdu->elem.in_sg, pdu->elem.in_num,
84
                             offset, size, 1);
85
}
86

  
87
static int pdu_copy_sg(V9fsPDU *pdu, size_t offset, int rx, struct iovec *sg)
88
{
89
    size_t pos = 0;
90
    int i, j;
91
    struct iovec *src_sg;
92
    unsigned int num;
93

  
94
    if (rx) {
95
        src_sg = pdu->elem.in_sg;
96
        num = pdu->elem.in_num;
97
    } else {
98
        src_sg = pdu->elem.out_sg;
99
        num = pdu->elem.out_num;
100
    }
101

  
102
    j = 0;
103
    for (i = 0; i < num; i++) {
104
        if (offset <= pos) {
105
            sg[j].iov_base = src_sg[i].iov_base;
106
            sg[j].iov_len = src_sg[i].iov_len;
107
            j++;
108
        } else if (offset < (src_sg[i].iov_len + pos)) {
109
            sg[j].iov_base = src_sg[i].iov_base;
110
            sg[j].iov_len = src_sg[i].iov_len;
111
            sg[j].iov_base += (offset - pos);
112
            sg[j].iov_len -= (offset - pos);
113
            j++;
114
        }
115
        pos += src_sg[i].iov_len;
116
    }
117

  
118
    return j;
119
}
120

  
121
static size_t pdu_unmarshal(V9fsPDU *pdu, size_t offset, const char *fmt, ...)
122
{
123
    size_t old_offset = offset;
124
    va_list ap;
125
    int i;
126

  
127
    va_start(ap, fmt);
128
    for (i = 0; fmt[i]; i++) {
129
        switch (fmt[i]) {
130
        case 'b': {
131
            uint8_t *valp = va_arg(ap, uint8_t *);
132
            offset += pdu_unpack(valp, pdu, offset, sizeof(*valp));
133
            break;
134
        }
135
        case 'w': {
136
            uint16_t val, *valp;
137
            valp = va_arg(ap, uint16_t *);
138
            val = le16_to_cpupu(valp);
139
            offset += pdu_unpack(&val, pdu, offset, sizeof(val));
140
            *valp = val;
141
            break;
142
        }
143
        case 'd': {
144
            uint32_t val, *valp;
145
            valp = va_arg(ap, uint32_t *);
146
            val = le32_to_cpupu(valp);
147
            offset += pdu_unpack(&val, pdu, offset, sizeof(val));
148
            *valp = val;
149
            break;
150
        }
151
        case 'q': {
152
            uint64_t val, *valp;
153
            valp = va_arg(ap, uint64_t *);
154
            val = le64_to_cpup(valp);
155
            offset += pdu_unpack(&val, pdu, offset, sizeof(val));
156
            *valp = val;
157
            break;
158
        }
159
        case 'v': {
160
            struct iovec *iov = va_arg(ap, struct iovec *);
161
            int *iovcnt = va_arg(ap, int *);
162
            *iovcnt = pdu_copy_sg(pdu, offset, 0, iov);
163
            break;
164
        }
165
        case 's': {
166
            V9fsString *str = va_arg(ap, V9fsString *);
167
            offset += pdu_unmarshal(pdu, offset, "w", &str->size);
168
            /* FIXME: sanity check str->size */
169
            str->data = qemu_malloc(str->size + 1);
170
            offset += pdu_unpack(str->data, pdu, offset, str->size);
171
            str->data[str->size] = 0;
172
            break;
173
        }
174
        case 'Q': {
175
            V9fsQID *qidp = va_arg(ap, V9fsQID *);
176
            offset += pdu_unmarshal(pdu, offset, "bdq",
177
                        &qidp->type, &qidp->version, &qidp->path);
178
            break;
179
        }
180
        case 'S': {
181
            V9fsStat *statp = va_arg(ap, V9fsStat *);
182
            offset += pdu_unmarshal(pdu, offset, "wwdQdddqsssssddd",
183
                        &statp->size, &statp->type, &statp->dev,
184
                        &statp->qid, &statp->mode, &statp->atime,
185
                        &statp->mtime, &statp->length,
186
                        &statp->name, &statp->uid, &statp->gid,
187
                        &statp->muid, &statp->extension,
188
                        &statp->n_uid, &statp->n_gid,
189
                        &statp->n_muid);
190
            break;
191
        }
192
        default:
193
            break;
194
        }
195
    }
196

  
197
    va_end(ap);
198

  
199
    return offset - old_offset;
200
}
201

  
202
static size_t pdu_marshal(V9fsPDU *pdu, size_t offset, const char *fmt, ...)
203
{
204
    size_t old_offset = offset;
205
    va_list ap;
206
    int i;
207

  
208
    va_start(ap, fmt);
209
    for (i = 0; fmt[i]; i++) {
210
        switch (fmt[i]) {
211
        case 'b': {
212
            uint8_t val = va_arg(ap, int);
213
            offset += pdu_pack(pdu, offset, &val, sizeof(val));
214
            break;
215
        }
216
        case 'w': {
217
            uint16_t val;
218
            cpu_to_le16w(&val, va_arg(ap, int));
219
            offset += pdu_pack(pdu, offset, &val, sizeof(val));
220
            break;
221
        }
222
        case 'd': {
223
            uint32_t val;
224
            cpu_to_le32w(&val, va_arg(ap, uint32_t));
225
            offset += pdu_pack(pdu, offset, &val, sizeof(val));
226
            break;
227
        }
228
        case 'q': {
229
            uint64_t val;
230
            cpu_to_le64w(&val, va_arg(ap, uint64_t));
231
            offset += pdu_pack(pdu, offset, &val, sizeof(val));
232
            break;
233
        }
234
        case 'v': {
235
            struct iovec *iov = va_arg(ap, struct iovec *);
236
            int *iovcnt = va_arg(ap, int *);
237
            *iovcnt = pdu_copy_sg(pdu, offset, 1, iov);
238
            break;
239
        }
240
        case 's': {
241
            V9fsString *str = va_arg(ap, V9fsString *);
242
            offset += pdu_marshal(pdu, offset, "w", str->size);
243
            offset += pdu_pack(pdu, offset, str->data, str->size);
244
            break;
245
        }
246
        case 'Q': {
247
            V9fsQID *qidp = va_arg(ap, V9fsQID *);
248
            offset += pdu_marshal(pdu, offset, "bdq",
249
                        qidp->type, qidp->version, qidp->path);
250
            break;
251
        }
252
        case 'S': {
253
            V9fsStat *statp = va_arg(ap, V9fsStat *);
254
            offset += pdu_marshal(pdu, offset, "wwdQdddqsssssddd",
255
                        statp->size, statp->type, statp->dev,
256
                        &statp->qid, statp->mode, statp->atime,
257
                        statp->mtime, statp->length, &statp->name,
258
                        &statp->uid, &statp->gid, &statp->muid,
259
                        &statp->extension, statp->n_uid,
260
                        statp->n_gid, statp->n_muid);
261
            break;
262
        }
263
        default:
264
            break;
265
        }
266
    }
267
    va_end(ap);
268

  
269
    return offset - old_offset;
270
}
271

  
272
static void complete_pdu(V9fsState *s, V9fsPDU *pdu, ssize_t len)
273
{
274
    int8_t id = pdu->id + 1; /* Response */
275

  
276
    if (len < 0) {
277
        V9fsString str;
278
        int err = -len;
279

  
280
        str.data = strerror(err);
281
        str.size = strlen(str.data);
282

  
283
        len = 7;
284
        len += pdu_marshal(pdu, len, "s", &str);
285
        if (dotu) {
286
            len += pdu_marshal(pdu, len, "d", err);
287
        }
288

  
289
        id = P9_RERROR;
290
    }
291

  
292
    /* fill out the header */
293
    pdu_marshal(pdu, 0, "dbw", (int32_t)len, id, pdu->tag);
294

  
295
    /* keep these in sync */
296
    pdu->size = len;
297
    pdu->id = id;
298

  
299
    /* push onto queue and notify */
300
    virtqueue_push(s->vq, &pdu->elem, len);
301

  
302
    /* FIXME: we should batch these completions */
303
    virtio_notify(&s->vdev, s->vq);
304

  
305
    free_pdu(s, pdu);
306
}
307

  
308
static void v9fs_dummy(V9fsState *s, V9fsPDU *pdu)
309
{
310
    /* Note: The following have been added to prevent GCC from complaining
311
     * They will be removed in the subsequent patches */
312
    (void)pdu_unmarshal;
313
    (void) complete_pdu;
314

  
315
}
74 316
static void v9fs_version(V9fsState *s, V9fsPDU *pdu)
75 317
{
76 318
    if (debug_9p_pdu) {
......
135 377

  
136 378
static void v9fs_flush(V9fsState *s, V9fsPDU *pdu)
137 379
{
380
    v9fs_dummy(s, pdu);
138 381
    if (debug_9p_pdu) {
139 382
        pprint_pdu(pdu);
140 383
    }

Also available in: Unified diff