Revision 10b468bd hw/virtio-9p.c
b/hw/virtio-9p.c | ||
---|---|---|
278 | 278 |
value, size); |
279 | 279 |
} |
280 | 280 |
|
281 |
static int v9fs_do_lsetxattr(V9fsState *s, V9fsString *path, |
|
282 |
V9fsString *xattr_name, |
|
283 |
void *value, size_t size, int flags) |
|
284 |
{ |
|
285 |
return s->ops->lsetxattr(&s->ctx, path->data, |
|
286 |
xattr_name->data, value, size, flags); |
|
287 |
} |
|
288 |
|
|
281 | 289 |
static void v9fs_string_init(V9fsString *str) |
282 | 290 |
{ |
283 | 291 |
str->data = NULL; |
... | ... | |
431 | 439 |
return f; |
432 | 440 |
} |
433 | 441 |
|
442 |
static int v9fs_xattr_fid_clunk(V9fsState *s, V9fsFidState *fidp) |
|
443 |
{ |
|
444 |
int retval = 0; |
|
445 |
|
|
446 |
if (fidp->fs.xattr.copied_len == -1) { |
|
447 |
/* getxattr/listxattr fid */ |
|
448 |
goto free_value; |
|
449 |
} |
|
450 |
/* |
|
451 |
* if this is fid for setxattr. clunk should |
|
452 |
* result in setxattr localcall |
|
453 |
*/ |
|
454 |
if (fidp->fs.xattr.len != fidp->fs.xattr.copied_len) { |
|
455 |
/* clunk after partial write */ |
|
456 |
retval = -EINVAL; |
|
457 |
goto free_out; |
|
458 |
} |
|
459 |
retval = v9fs_do_lsetxattr(s, &fidp->path, &fidp->fs.xattr.name, |
|
460 |
fidp->fs.xattr.value, |
|
461 |
fidp->fs.xattr.len, |
|
462 |
fidp->fs.xattr.flags); |
|
463 |
free_out: |
|
464 |
v9fs_string_free(&fidp->fs.xattr.name); |
|
465 |
free_value: |
|
466 |
if (fidp->fs.xattr.value) { |
|
467 |
qemu_free(fidp->fs.xattr.value); |
|
468 |
} |
|
469 |
return retval; |
|
470 |
} |
|
471 |
|
|
434 | 472 |
static int free_fid(V9fsState *s, int32_t fid) |
435 | 473 |
{ |
474 |
int retval = 0; |
|
436 | 475 |
V9fsFidState **fidpp, *fidp; |
437 | 476 |
|
438 | 477 |
for (fidpp = &s->fid_list; *fidpp; fidpp = &(*fidpp)->next) { |
... | ... | |
453 | 492 |
} else if (fidp->fid_type == P9_FID_DIR) { |
454 | 493 |
v9fs_do_closedir(s, fidp->fs.dir); |
455 | 494 |
} else if (fidp->fid_type == P9_FID_XATTR) { |
456 |
if (fidp->fs.xattr.value) { |
|
457 |
qemu_free(fidp->fs.xattr.value); |
|
458 |
} |
|
495 |
retval = v9fs_xattr_fid_clunk(s, fidp); |
|
459 | 496 |
} |
460 | 497 |
v9fs_string_free(&fidp->path); |
461 | 498 |
qemu_free(fidp); |
462 | 499 |
|
463 |
return 0;
|
|
500 |
return retval;
|
|
464 | 501 |
} |
465 | 502 |
|
466 | 503 |
#define P9_QID_TYPE_DIR 0x80 |
... | ... | |
2211 | 2248 |
qemu_free(vs); |
2212 | 2249 |
} |
2213 | 2250 |
|
2251 |
static void v9fs_xattr_write(V9fsState *s, V9fsWriteState *vs) |
|
2252 |
{ |
|
2253 |
int i, to_copy; |
|
2254 |
ssize_t err = 0; |
|
2255 |
int write_count; |
|
2256 |
int64_t xattr_len; |
|
2257 |
|
|
2258 |
xattr_len = vs->fidp->fs.xattr.len; |
|
2259 |
write_count = xattr_len - vs->off; |
|
2260 |
if (write_count > vs->count) { |
|
2261 |
write_count = vs->count; |
|
2262 |
} else if (write_count < 0) { |
|
2263 |
/* |
|
2264 |
* write beyond XATTR value len specified in |
|
2265 |
* xattrcreate |
|
2266 |
*/ |
|
2267 |
err = -ENOSPC; |
|
2268 |
goto out; |
|
2269 |
} |
|
2270 |
vs->offset += pdu_marshal(vs->pdu, vs->offset, "d", write_count); |
|
2271 |
err = vs->offset; |
|
2272 |
vs->fidp->fs.xattr.copied_len += write_count; |
|
2273 |
/* |
|
2274 |
* Now copy the content from sg list |
|
2275 |
*/ |
|
2276 |
for (i = 0; i < vs->cnt; i++) { |
|
2277 |
if (write_count > vs->sg[i].iov_len) { |
|
2278 |
to_copy = vs->sg[i].iov_len; |
|
2279 |
} else { |
|
2280 |
to_copy = write_count; |
|
2281 |
} |
|
2282 |
memcpy((char *)vs->fidp->fs.xattr.value + vs->off, |
|
2283 |
vs->sg[i].iov_base, to_copy); |
|
2284 |
/* updating vs->off since we are not using below */ |
|
2285 |
vs->off += to_copy; |
|
2286 |
write_count -= to_copy; |
|
2287 |
} |
|
2288 |
out: |
|
2289 |
complete_pdu(s, vs->pdu, err); |
|
2290 |
qemu_free(vs); |
|
2291 |
} |
|
2292 |
|
|
2214 | 2293 |
static void v9fs_write(V9fsState *s, V9fsPDU *pdu) |
2215 | 2294 |
{ |
2216 | 2295 |
int32_t fid; |
... | ... | |
2226 | 2305 |
vs->len = 0; |
2227 | 2306 |
|
2228 | 2307 |
pdu_unmarshal(vs->pdu, vs->offset, "dqdv", &fid, &vs->off, &vs->count, |
2229 |
vs->sg, &vs->cnt);
|
|
2308 |
vs->sg, &vs->cnt); |
|
2230 | 2309 |
|
2231 | 2310 |
vs->fidp = lookup_fid(s, fid); |
2232 | 2311 |
if (vs->fidp == NULL) { |
... | ... | |
2234 | 2313 |
goto out; |
2235 | 2314 |
} |
2236 | 2315 |
|
2237 |
if (vs->fidp->fs.fd == -1) { |
|
2316 |
if (vs->fidp->fid_type == P9_FID_FILE) { |
|
2317 |
if (vs->fidp->fs.fd == -1) { |
|
2318 |
err = -EINVAL; |
|
2319 |
goto out; |
|
2320 |
} |
|
2321 |
} else if (vs->fidp->fid_type == P9_FID_XATTR) { |
|
2322 |
/* |
|
2323 |
* setxattr operation |
|
2324 |
*/ |
|
2325 |
v9fs_xattr_write(s, vs); |
|
2326 |
return; |
|
2327 |
} else { |
|
2238 | 2328 |
err = -EINVAL; |
2239 | 2329 |
goto out; |
2240 | 2330 |
} |
2241 |
|
|
2242 | 2331 |
err = v9fs_do_lseek(s, vs->fidp->fs.fd, vs->off, SEEK_SET); |
2243 | 2332 |
|
2244 | 2333 |
v9fs_write_post_lseek(s, vs, err); |
... | ... | |
3276 | 3365 |
qemu_free(vs); |
3277 | 3366 |
} |
3278 | 3367 |
|
3368 |
static void v9fs_xattrcreate(V9fsState *s, V9fsPDU *pdu) |
|
3369 |
{ |
|
3370 |
int flags; |
|
3371 |
int32_t fid; |
|
3372 |
ssize_t err = 0; |
|
3373 |
V9fsXattrState *vs; |
|
3374 |
|
|
3375 |
vs = qemu_malloc(sizeof(*vs)); |
|
3376 |
vs->pdu = pdu; |
|
3377 |
vs->offset = 7; |
|
3378 |
|
|
3379 |
pdu_unmarshal(vs->pdu, vs->offset, "dsqd", |
|
3380 |
&fid, &vs->name, &vs->size, &flags); |
|
3381 |
|
|
3382 |
vs->file_fidp = lookup_fid(s, fid); |
|
3383 |
if (vs->file_fidp == NULL) { |
|
3384 |
err = -EINVAL; |
|
3385 |
goto out; |
|
3386 |
} |
|
3387 |
|
|
3388 |
/* Make the file fid point to xattr */ |
|
3389 |
vs->xattr_fidp = vs->file_fidp; |
|
3390 |
vs->xattr_fidp->fid_type = P9_FID_XATTR; |
|
3391 |
vs->xattr_fidp->fs.xattr.copied_len = 0; |
|
3392 |
vs->xattr_fidp->fs.xattr.len = vs->size; |
|
3393 |
vs->xattr_fidp->fs.xattr.flags = flags; |
|
3394 |
v9fs_string_init(&vs->xattr_fidp->fs.xattr.name); |
|
3395 |
v9fs_string_copy(&vs->xattr_fidp->fs.xattr.name, &vs->name); |
|
3396 |
vs->xattr_fidp->fs.xattr.value = qemu_malloc(vs->size); |
|
3397 |
|
|
3398 |
out: |
|
3399 |
complete_pdu(s, vs->pdu, err); |
|
3400 |
v9fs_string_free(&vs->name); |
|
3401 |
qemu_free(vs); |
|
3402 |
} |
|
3279 | 3403 |
|
3280 | 3404 |
typedef void (pdu_handler_t)(V9fsState *s, V9fsPDU *pdu); |
3281 | 3405 |
|
... | ... | |
3285 | 3409 |
[P9_TGETATTR] = v9fs_getattr, |
3286 | 3410 |
[P9_TSETATTR] = v9fs_setattr, |
3287 | 3411 |
[P9_TXATTRWALK] = v9fs_xattrwalk, |
3412 |
[P9_TXATTRCREATE] = v9fs_xattrcreate, |
|
3288 | 3413 |
[P9_TMKNOD] = v9fs_mknod, |
3289 | 3414 |
[P9_TRENAME] = v9fs_rename, |
3290 | 3415 |
[P9_TMKDIR] = v9fs_mkdir, |
Also available in: Unified diff