qemu with hax to log dma reads & writes jcs.org/2018/11/12/vfio
at master 2688 lines 72 kB view raw
1/* 2 * FUSE: Filesystem in Userspace 3 * Copyright (C) 2001-2007 Miklos Szeredi <miklos@szeredi.hu> 4 * 5 * Implementation of (most of) the low-level FUSE API. The session loop 6 * functions are implemented in separate files. 7 * 8 * This program can be distributed under the terms of the GNU LGPLv2. 9 * See the file COPYING.LIB 10 */ 11 12#include "qemu/osdep.h" 13#include "fuse_i.h" 14#include "standard-headers/linux/fuse.h" 15#include "fuse_misc.h" 16#include "fuse_opt.h" 17#include "fuse_virtio.h" 18 19#include <assert.h> 20#include <errno.h> 21#include <glib.h> 22#include <limits.h> 23#include <stdbool.h> 24#include <stddef.h> 25#include <stdio.h> 26#include <stdlib.h> 27#include <string.h> 28#include <sys/file.h> 29#include <unistd.h> 30 31#define THREAD_POOL_SIZE 64 32 33#define OFFSET_MAX 0x7fffffffffffffffLL 34 35struct fuse_pollhandle { 36 uint64_t kh; 37 struct fuse_session *se; 38}; 39 40static size_t pagesize; 41 42static __attribute__((constructor)) void fuse_ll_init_pagesize(void) 43{ 44 pagesize = getpagesize(); 45} 46 47static void convert_stat(const struct stat *stbuf, struct fuse_attr *attr) 48{ 49 *attr = (struct fuse_attr){ 50 .ino = stbuf->st_ino, 51 .mode = stbuf->st_mode, 52 .nlink = stbuf->st_nlink, 53 .uid = stbuf->st_uid, 54 .gid = stbuf->st_gid, 55 .rdev = stbuf->st_rdev, 56 .size = stbuf->st_size, 57 .blksize = stbuf->st_blksize, 58 .blocks = stbuf->st_blocks, 59 .atime = stbuf->st_atime, 60 .mtime = stbuf->st_mtime, 61 .ctime = stbuf->st_ctime, 62 .atimensec = ST_ATIM_NSEC(stbuf), 63 .mtimensec = ST_MTIM_NSEC(stbuf), 64 .ctimensec = ST_CTIM_NSEC(stbuf), 65 }; 66} 67 68static void convert_attr(const struct fuse_setattr_in *attr, struct stat *stbuf) 69{ 70 stbuf->st_mode = attr->mode; 71 stbuf->st_uid = attr->uid; 72 stbuf->st_gid = attr->gid; 73 stbuf->st_size = attr->size; 74 stbuf->st_atime = attr->atime; 75 stbuf->st_mtime = attr->mtime; 76 stbuf->st_ctime = attr->ctime; 77 ST_ATIM_NSEC_SET(stbuf, attr->atimensec); 78 ST_MTIM_NSEC_SET(stbuf, attr->mtimensec); 79 ST_CTIM_NSEC_SET(stbuf, attr->ctimensec); 80} 81 82static size_t iov_length(const struct iovec *iov, size_t count) 83{ 84 size_t seg; 85 size_t ret = 0; 86 87 for (seg = 0; seg < count; seg++) { 88 ret += iov[seg].iov_len; 89 } 90 return ret; 91} 92 93static void list_init_req(struct fuse_req *req) 94{ 95 req->next = req; 96 req->prev = req; 97} 98 99static void list_del_req(struct fuse_req *req) 100{ 101 struct fuse_req *prev = req->prev; 102 struct fuse_req *next = req->next; 103 prev->next = next; 104 next->prev = prev; 105} 106 107static void list_add_req(struct fuse_req *req, struct fuse_req *next) 108{ 109 struct fuse_req *prev = next->prev; 110 req->next = next; 111 req->prev = prev; 112 prev->next = req; 113 next->prev = req; 114} 115 116static void destroy_req(fuse_req_t req) 117{ 118 pthread_mutex_destroy(&req->lock); 119 free(req); 120} 121 122void fuse_free_req(fuse_req_t req) 123{ 124 int ctr; 125 struct fuse_session *se = req->se; 126 127 pthread_mutex_lock(&se->lock); 128 req->u.ni.func = NULL; 129 req->u.ni.data = NULL; 130 list_del_req(req); 131 ctr = --req->ctr; 132 req->ch = NULL; 133 pthread_mutex_unlock(&se->lock); 134 if (!ctr) { 135 destroy_req(req); 136 } 137} 138 139static struct fuse_req *fuse_ll_alloc_req(struct fuse_session *se) 140{ 141 struct fuse_req *req; 142 143 req = (struct fuse_req *)calloc(1, sizeof(struct fuse_req)); 144 if (req == NULL) { 145 fuse_log(FUSE_LOG_ERR, "fuse: failed to allocate request\n"); 146 } else { 147 req->se = se; 148 req->ctr = 1; 149 list_init_req(req); 150 fuse_mutex_init(&req->lock); 151 } 152 153 return req; 154} 155 156/* Send data. If *ch* is NULL, send via session master fd */ 157static int fuse_send_msg(struct fuse_session *se, struct fuse_chan *ch, 158 struct iovec *iov, int count) 159{ 160 struct fuse_out_header *out = iov[0].iov_base; 161 162 out->len = iov_length(iov, count); 163 if (out->unique == 0) { 164 fuse_log(FUSE_LOG_DEBUG, "NOTIFY: code=%d length=%u\n", out->error, 165 out->len); 166 } else if (out->error) { 167 fuse_log(FUSE_LOG_DEBUG, 168 " unique: %llu, error: %i (%s), outsize: %i\n", 169 (unsigned long long)out->unique, out->error, 170 strerror(-out->error), out->len); 171 } else { 172 fuse_log(FUSE_LOG_DEBUG, " unique: %llu, success, outsize: %i\n", 173 (unsigned long long)out->unique, out->len); 174 } 175 176 if (fuse_lowlevel_is_virtio(se)) { 177 return virtio_send_msg(se, ch, iov, count); 178 } 179 180 abort(); /* virtio should have taken it before here */ 181 return 0; 182} 183 184 185int fuse_send_reply_iov_nofree(fuse_req_t req, int error, struct iovec *iov, 186 int count) 187{ 188 struct fuse_out_header out = { 189 .unique = req->unique, 190 .error = error, 191 }; 192 193 if (error <= -1000 || error > 0) { 194 fuse_log(FUSE_LOG_ERR, "fuse: bad error value: %i\n", error); 195 out.error = -ERANGE; 196 } 197 198 iov[0].iov_base = &out; 199 iov[0].iov_len = sizeof(struct fuse_out_header); 200 201 return fuse_send_msg(req->se, req->ch, iov, count); 202} 203 204static int send_reply_iov(fuse_req_t req, int error, struct iovec *iov, 205 int count) 206{ 207 int res; 208 209 res = fuse_send_reply_iov_nofree(req, error, iov, count); 210 fuse_free_req(req); 211 return res; 212} 213 214static int send_reply(fuse_req_t req, int error, const void *arg, 215 size_t argsize) 216{ 217 struct iovec iov[2]; 218 int count = 1; 219 if (argsize) { 220 iov[1].iov_base = (void *)arg; 221 iov[1].iov_len = argsize; 222 count++; 223 } 224 return send_reply_iov(req, error, iov, count); 225} 226 227int fuse_reply_iov(fuse_req_t req, const struct iovec *iov, int count) 228{ 229 int res; 230 struct iovec *padded_iov; 231 232 padded_iov = malloc((count + 1) * sizeof(struct iovec)); 233 if (padded_iov == NULL) { 234 return fuse_reply_err(req, ENOMEM); 235 } 236 237 memcpy(padded_iov + 1, iov, count * sizeof(struct iovec)); 238 count++; 239 240 res = send_reply_iov(req, 0, padded_iov, count); 241 free(padded_iov); 242 243 return res; 244} 245 246 247/* 248 * 'buf` is allowed to be empty so that the proper size may be 249 * allocated by the caller 250 */ 251size_t fuse_add_direntry(fuse_req_t req, char *buf, size_t bufsize, 252 const char *name, const struct stat *stbuf, off_t off) 253{ 254 (void)req; 255 size_t namelen; 256 size_t entlen; 257 size_t entlen_padded; 258 struct fuse_dirent *dirent; 259 260 namelen = strlen(name); 261 entlen = FUSE_NAME_OFFSET + namelen; 262 entlen_padded = FUSE_DIRENT_ALIGN(entlen); 263 264 if ((buf == NULL) || (entlen_padded > bufsize)) { 265 return entlen_padded; 266 } 267 268 dirent = (struct fuse_dirent *)buf; 269 dirent->ino = stbuf->st_ino; 270 dirent->off = off; 271 dirent->namelen = namelen; 272 dirent->type = (stbuf->st_mode & S_IFMT) >> 12; 273 memcpy(dirent->name, name, namelen); 274 memset(dirent->name + namelen, 0, entlen_padded - entlen); 275 276 return entlen_padded; 277} 278 279static void convert_statfs(const struct statvfs *stbuf, 280 struct fuse_kstatfs *kstatfs) 281{ 282 *kstatfs = (struct fuse_kstatfs){ 283 .bsize = stbuf->f_bsize, 284 .frsize = stbuf->f_frsize, 285 .blocks = stbuf->f_blocks, 286 .bfree = stbuf->f_bfree, 287 .bavail = stbuf->f_bavail, 288 .files = stbuf->f_files, 289 .ffree = stbuf->f_ffree, 290 .namelen = stbuf->f_namemax, 291 }; 292} 293 294static int send_reply_ok(fuse_req_t req, const void *arg, size_t argsize) 295{ 296 return send_reply(req, 0, arg, argsize); 297} 298 299int fuse_reply_err(fuse_req_t req, int err) 300{ 301 return send_reply(req, -err, NULL, 0); 302} 303 304void fuse_reply_none(fuse_req_t req) 305{ 306 fuse_free_req(req); 307} 308 309static unsigned long calc_timeout_sec(double t) 310{ 311 if (t > (double)ULONG_MAX) { 312 return ULONG_MAX; 313 } else if (t < 0.0) { 314 return 0; 315 } else { 316 return (unsigned long)t; 317 } 318} 319 320static unsigned int calc_timeout_nsec(double t) 321{ 322 double f = t - (double)calc_timeout_sec(t); 323 if (f < 0.0) { 324 return 0; 325 } else if (f >= 0.999999999) { 326 return 999999999; 327 } else { 328 return (unsigned int)(f * 1.0e9); 329 } 330} 331 332static void fill_entry(struct fuse_entry_out *arg, 333 const struct fuse_entry_param *e) 334{ 335 *arg = (struct fuse_entry_out){ 336 .nodeid = e->ino, 337 .generation = e->generation, 338 .entry_valid = calc_timeout_sec(e->entry_timeout), 339 .entry_valid_nsec = calc_timeout_nsec(e->entry_timeout), 340 .attr_valid = calc_timeout_sec(e->attr_timeout), 341 .attr_valid_nsec = calc_timeout_nsec(e->attr_timeout), 342 }; 343 convert_stat(&e->attr, &arg->attr); 344} 345 346/* 347 * `buf` is allowed to be empty so that the proper size may be 348 * allocated by the caller 349 */ 350size_t fuse_add_direntry_plus(fuse_req_t req, char *buf, size_t bufsize, 351 const char *name, 352 const struct fuse_entry_param *e, off_t off) 353{ 354 (void)req; 355 size_t namelen; 356 size_t entlen; 357 size_t entlen_padded; 358 359 namelen = strlen(name); 360 entlen = FUSE_NAME_OFFSET_DIRENTPLUS + namelen; 361 entlen_padded = FUSE_DIRENT_ALIGN(entlen); 362 if ((buf == NULL) || (entlen_padded > bufsize)) { 363 return entlen_padded; 364 } 365 366 struct fuse_direntplus *dp = (struct fuse_direntplus *)buf; 367 memset(&dp->entry_out, 0, sizeof(dp->entry_out)); 368 fill_entry(&dp->entry_out, e); 369 370 struct fuse_dirent *dirent = &dp->dirent; 371 *dirent = (struct fuse_dirent){ 372 .ino = e->attr.st_ino, 373 .off = off, 374 .namelen = namelen, 375 .type = (e->attr.st_mode & S_IFMT) >> 12, 376 }; 377 memcpy(dirent->name, name, namelen); 378 memset(dirent->name + namelen, 0, entlen_padded - entlen); 379 380 return entlen_padded; 381} 382 383static void fill_open(struct fuse_open_out *arg, const struct fuse_file_info *f) 384{ 385 arg->fh = f->fh; 386 if (f->direct_io) { 387 arg->open_flags |= FOPEN_DIRECT_IO; 388 } 389 if (f->keep_cache) { 390 arg->open_flags |= FOPEN_KEEP_CACHE; 391 } 392 if (f->cache_readdir) { 393 arg->open_flags |= FOPEN_CACHE_DIR; 394 } 395 if (f->nonseekable) { 396 arg->open_flags |= FOPEN_NONSEEKABLE; 397 } 398} 399 400int fuse_reply_entry(fuse_req_t req, const struct fuse_entry_param *e) 401{ 402 struct fuse_entry_out arg; 403 size_t size = sizeof(arg); 404 405 memset(&arg, 0, sizeof(arg)); 406 fill_entry(&arg, e); 407 return send_reply_ok(req, &arg, size); 408} 409 410int fuse_reply_create(fuse_req_t req, const struct fuse_entry_param *e, 411 const struct fuse_file_info *f) 412{ 413 char buf[sizeof(struct fuse_entry_out) + sizeof(struct fuse_open_out)]; 414 size_t entrysize = sizeof(struct fuse_entry_out); 415 struct fuse_entry_out *earg = (struct fuse_entry_out *)buf; 416 struct fuse_open_out *oarg = (struct fuse_open_out *)(buf + entrysize); 417 418 memset(buf, 0, sizeof(buf)); 419 fill_entry(earg, e); 420 fill_open(oarg, f); 421 return send_reply_ok(req, buf, entrysize + sizeof(struct fuse_open_out)); 422} 423 424int fuse_reply_attr(fuse_req_t req, const struct stat *attr, 425 double attr_timeout) 426{ 427 struct fuse_attr_out arg; 428 size_t size = sizeof(arg); 429 430 memset(&arg, 0, sizeof(arg)); 431 arg.attr_valid = calc_timeout_sec(attr_timeout); 432 arg.attr_valid_nsec = calc_timeout_nsec(attr_timeout); 433 convert_stat(attr, &arg.attr); 434 435 return send_reply_ok(req, &arg, size); 436} 437 438int fuse_reply_readlink(fuse_req_t req, const char *linkname) 439{ 440 return send_reply_ok(req, linkname, strlen(linkname)); 441} 442 443int fuse_reply_open(fuse_req_t req, const struct fuse_file_info *f) 444{ 445 struct fuse_open_out arg; 446 447 memset(&arg, 0, sizeof(arg)); 448 fill_open(&arg, f); 449 return send_reply_ok(req, &arg, sizeof(arg)); 450} 451 452int fuse_reply_write(fuse_req_t req, size_t count) 453{ 454 struct fuse_write_out arg; 455 456 memset(&arg, 0, sizeof(arg)); 457 arg.size = count; 458 459 return send_reply_ok(req, &arg, sizeof(arg)); 460} 461 462int fuse_reply_buf(fuse_req_t req, const char *buf, size_t size) 463{ 464 return send_reply_ok(req, buf, size); 465} 466 467static int fuse_send_data_iov_fallback(struct fuse_session *se, 468 struct fuse_chan *ch, struct iovec *iov, 469 int iov_count, struct fuse_bufvec *buf, 470 size_t len) 471{ 472 /* Optimize common case */ 473 if (buf->count == 1 && buf->idx == 0 && buf->off == 0 && 474 !(buf->buf[0].flags & FUSE_BUF_IS_FD)) { 475 /* 476 * FIXME: also avoid memory copy if there are multiple buffers 477 * but none of them contain an fd 478 */ 479 480 iov[iov_count].iov_base = buf->buf[0].mem; 481 iov[iov_count].iov_len = len; 482 iov_count++; 483 return fuse_send_msg(se, ch, iov, iov_count); 484 } 485 486 if (fuse_lowlevel_is_virtio(se) && buf->count == 1 && 487 buf->buf[0].flags == (FUSE_BUF_IS_FD | FUSE_BUF_FD_SEEK)) { 488 return virtio_send_data_iov(se, ch, iov, iov_count, buf, len); 489 } 490 491 abort(); /* Will have taken vhost path */ 492 return 0; 493} 494 495static int fuse_send_data_iov(struct fuse_session *se, struct fuse_chan *ch, 496 struct iovec *iov, int iov_count, 497 struct fuse_bufvec *buf) 498{ 499 size_t len = fuse_buf_size(buf); 500 501 return fuse_send_data_iov_fallback(se, ch, iov, iov_count, buf, len); 502} 503 504int fuse_reply_data(fuse_req_t req, struct fuse_bufvec *bufv) 505{ 506 struct iovec iov[2]; 507 struct fuse_out_header out = { 508 .unique = req->unique, 509 }; 510 int res; 511 512 iov[0].iov_base = &out; 513 iov[0].iov_len = sizeof(struct fuse_out_header); 514 515 res = fuse_send_data_iov(req->se, req->ch, iov, 1, bufv); 516 if (res <= 0) { 517 fuse_free_req(req); 518 return res; 519 } else { 520 return fuse_reply_err(req, res); 521 } 522} 523 524int fuse_reply_statfs(fuse_req_t req, const struct statvfs *stbuf) 525{ 526 struct fuse_statfs_out arg; 527 size_t size = sizeof(arg); 528 529 memset(&arg, 0, sizeof(arg)); 530 convert_statfs(stbuf, &arg.st); 531 532 return send_reply_ok(req, &arg, size); 533} 534 535int fuse_reply_xattr(fuse_req_t req, size_t count) 536{ 537 struct fuse_getxattr_out arg; 538 539 memset(&arg, 0, sizeof(arg)); 540 arg.size = count; 541 542 return send_reply_ok(req, &arg, sizeof(arg)); 543} 544 545int fuse_reply_lock(fuse_req_t req, const struct flock *lock) 546{ 547 struct fuse_lk_out arg; 548 549 memset(&arg, 0, sizeof(arg)); 550 arg.lk.type = lock->l_type; 551 if (lock->l_type != F_UNLCK) { 552 arg.lk.start = lock->l_start; 553 if (lock->l_len == 0) { 554 arg.lk.end = OFFSET_MAX; 555 } else { 556 arg.lk.end = lock->l_start + lock->l_len - 1; 557 } 558 } 559 arg.lk.pid = lock->l_pid; 560 return send_reply_ok(req, &arg, sizeof(arg)); 561} 562 563int fuse_reply_bmap(fuse_req_t req, uint64_t idx) 564{ 565 struct fuse_bmap_out arg; 566 567 memset(&arg, 0, sizeof(arg)); 568 arg.block = idx; 569 570 return send_reply_ok(req, &arg, sizeof(arg)); 571} 572 573static struct fuse_ioctl_iovec *fuse_ioctl_iovec_copy(const struct iovec *iov, 574 size_t count) 575{ 576 struct fuse_ioctl_iovec *fiov; 577 size_t i; 578 579 fiov = malloc(sizeof(fiov[0]) * count); 580 if (!fiov) { 581 return NULL; 582 } 583 584 for (i = 0; i < count; i++) { 585 fiov[i].base = (uintptr_t)iov[i].iov_base; 586 fiov[i].len = iov[i].iov_len; 587 } 588 589 return fiov; 590} 591 592int fuse_reply_ioctl_retry(fuse_req_t req, const struct iovec *in_iov, 593 size_t in_count, const struct iovec *out_iov, 594 size_t out_count) 595{ 596 struct fuse_ioctl_out arg; 597 struct fuse_ioctl_iovec *in_fiov = NULL; 598 struct fuse_ioctl_iovec *out_fiov = NULL; 599 struct iovec iov[4]; 600 size_t count = 1; 601 int res; 602 603 memset(&arg, 0, sizeof(arg)); 604 arg.flags |= FUSE_IOCTL_RETRY; 605 arg.in_iovs = in_count; 606 arg.out_iovs = out_count; 607 iov[count].iov_base = &arg; 608 iov[count].iov_len = sizeof(arg); 609 count++; 610 611 /* Can't handle non-compat 64bit ioctls on 32bit */ 612 if (sizeof(void *) == 4 && req->ioctl_64bit) { 613 res = fuse_reply_err(req, EINVAL); 614 goto out; 615 } 616 617 if (in_count) { 618 in_fiov = fuse_ioctl_iovec_copy(in_iov, in_count); 619 if (!in_fiov) { 620 goto enomem; 621 } 622 623 iov[count].iov_base = (void *)in_fiov; 624 iov[count].iov_len = sizeof(in_fiov[0]) * in_count; 625 count++; 626 } 627 if (out_count) { 628 out_fiov = fuse_ioctl_iovec_copy(out_iov, out_count); 629 if (!out_fiov) { 630 goto enomem; 631 } 632 633 iov[count].iov_base = (void *)out_fiov; 634 iov[count].iov_len = sizeof(out_fiov[0]) * out_count; 635 count++; 636 } 637 638 res = send_reply_iov(req, 0, iov, count); 639out: 640 free(in_fiov); 641 free(out_fiov); 642 643 return res; 644 645enomem: 646 res = fuse_reply_err(req, ENOMEM); 647 goto out; 648} 649 650int fuse_reply_ioctl(fuse_req_t req, int result, const void *buf, size_t size) 651{ 652 struct fuse_ioctl_out arg; 653 struct iovec iov[3]; 654 size_t count = 1; 655 656 memset(&arg, 0, sizeof(arg)); 657 arg.result = result; 658 iov[count].iov_base = &arg; 659 iov[count].iov_len = sizeof(arg); 660 count++; 661 662 if (size) { 663 iov[count].iov_base = (char *)buf; 664 iov[count].iov_len = size; 665 count++; 666 } 667 668 return send_reply_iov(req, 0, iov, count); 669} 670 671int fuse_reply_ioctl_iov(fuse_req_t req, int result, const struct iovec *iov, 672 int count) 673{ 674 struct iovec *padded_iov; 675 struct fuse_ioctl_out arg; 676 int res; 677 678 padded_iov = malloc((count + 2) * sizeof(struct iovec)); 679 if (padded_iov == NULL) { 680 return fuse_reply_err(req, ENOMEM); 681 } 682 683 memset(&arg, 0, sizeof(arg)); 684 arg.result = result; 685 padded_iov[1].iov_base = &arg; 686 padded_iov[1].iov_len = sizeof(arg); 687 688 memcpy(&padded_iov[2], iov, count * sizeof(struct iovec)); 689 690 res = send_reply_iov(req, 0, padded_iov, count + 2); 691 free(padded_iov); 692 693 return res; 694} 695 696int fuse_reply_poll(fuse_req_t req, unsigned revents) 697{ 698 struct fuse_poll_out arg; 699 700 memset(&arg, 0, sizeof(arg)); 701 arg.revents = revents; 702 703 return send_reply_ok(req, &arg, sizeof(arg)); 704} 705 706int fuse_reply_lseek(fuse_req_t req, off_t off) 707{ 708 struct fuse_lseek_out arg; 709 710 memset(&arg, 0, sizeof(arg)); 711 arg.offset = off; 712 713 return send_reply_ok(req, &arg, sizeof(arg)); 714} 715 716static void do_lookup(fuse_req_t req, fuse_ino_t nodeid, 717 struct fuse_mbuf_iter *iter) 718{ 719 const char *name = fuse_mbuf_iter_advance_str(iter); 720 if (!name) { 721 fuse_reply_err(req, EINVAL); 722 return; 723 } 724 725 if (req->se->op.lookup) { 726 req->se->op.lookup(req, nodeid, name); 727 } else { 728 fuse_reply_err(req, ENOSYS); 729 } 730} 731 732static void do_forget(fuse_req_t req, fuse_ino_t nodeid, 733 struct fuse_mbuf_iter *iter) 734{ 735 struct fuse_forget_in *arg; 736 737 arg = fuse_mbuf_iter_advance(iter, sizeof(*arg)); 738 if (!arg) { 739 fuse_reply_err(req, EINVAL); 740 return; 741 } 742 743 if (req->se->op.forget) { 744 req->se->op.forget(req, nodeid, arg->nlookup); 745 } else { 746 fuse_reply_none(req); 747 } 748} 749 750static void do_batch_forget(fuse_req_t req, fuse_ino_t nodeid, 751 struct fuse_mbuf_iter *iter) 752{ 753 struct fuse_batch_forget_in *arg; 754 struct fuse_forget_data *forgets; 755 size_t scount; 756 757 (void)nodeid; 758 759 arg = fuse_mbuf_iter_advance(iter, sizeof(*arg)); 760 if (!arg) { 761 fuse_reply_none(req); 762 return; 763 } 764 765 /* 766 * Prevent integer overflow. The compiler emits the following warning 767 * unless we use the scount local variable: 768 * 769 * error: comparison is always false due to limited range of data type 770 * [-Werror=type-limits] 771 * 772 * This may be true on 64-bit hosts but we need this check for 32-bit 773 * hosts. 774 */ 775 scount = arg->count; 776 if (scount > SIZE_MAX / sizeof(forgets[0])) { 777 fuse_reply_none(req); 778 return; 779 } 780 781 forgets = fuse_mbuf_iter_advance(iter, arg->count * sizeof(forgets[0])); 782 if (!forgets) { 783 fuse_reply_none(req); 784 return; 785 } 786 787 if (req->se->op.forget_multi) { 788 req->se->op.forget_multi(req, arg->count, forgets); 789 } else if (req->se->op.forget) { 790 unsigned int i; 791 792 for (i = 0; i < arg->count; i++) { 793 struct fuse_req *dummy_req; 794 795 dummy_req = fuse_ll_alloc_req(req->se); 796 if (dummy_req == NULL) { 797 break; 798 } 799 800 dummy_req->unique = req->unique; 801 dummy_req->ctx = req->ctx; 802 dummy_req->ch = NULL; 803 804 req->se->op.forget(dummy_req, forgets[i].ino, forgets[i].nlookup); 805 } 806 fuse_reply_none(req); 807 } else { 808 fuse_reply_none(req); 809 } 810} 811 812static void do_getattr(fuse_req_t req, fuse_ino_t nodeid, 813 struct fuse_mbuf_iter *iter) 814{ 815 struct fuse_file_info *fip = NULL; 816 struct fuse_file_info fi; 817 818 struct fuse_getattr_in *arg; 819 820 arg = fuse_mbuf_iter_advance(iter, sizeof(*arg)); 821 if (!arg) { 822 fuse_reply_err(req, EINVAL); 823 return; 824 } 825 826 if (arg->getattr_flags & FUSE_GETATTR_FH) { 827 memset(&fi, 0, sizeof(fi)); 828 fi.fh = arg->fh; 829 fip = &fi; 830 } 831 832 if (req->se->op.getattr) { 833 req->se->op.getattr(req, nodeid, fip); 834 } else { 835 fuse_reply_err(req, ENOSYS); 836 } 837} 838 839static void do_setattr(fuse_req_t req, fuse_ino_t nodeid, 840 struct fuse_mbuf_iter *iter) 841{ 842 if (req->se->op.setattr) { 843 struct fuse_setattr_in *arg; 844 struct fuse_file_info *fi = NULL; 845 struct fuse_file_info fi_store; 846 struct stat stbuf; 847 848 arg = fuse_mbuf_iter_advance(iter, sizeof(*arg)); 849 if (!arg) { 850 fuse_reply_err(req, EINVAL); 851 return; 852 } 853 854 memset(&stbuf, 0, sizeof(stbuf)); 855 convert_attr(arg, &stbuf); 856 if (arg->valid & FATTR_FH) { 857 arg->valid &= ~FATTR_FH; 858 memset(&fi_store, 0, sizeof(fi_store)); 859 fi = &fi_store; 860 fi->fh = arg->fh; 861 } 862 arg->valid &= FUSE_SET_ATTR_MODE | FUSE_SET_ATTR_UID | 863 FUSE_SET_ATTR_GID | FUSE_SET_ATTR_SIZE | 864 FUSE_SET_ATTR_ATIME | FUSE_SET_ATTR_MTIME | 865 FUSE_SET_ATTR_ATIME_NOW | FUSE_SET_ATTR_MTIME_NOW | 866 FUSE_SET_ATTR_CTIME; 867 868 req->se->op.setattr(req, nodeid, &stbuf, arg->valid, fi); 869 } else { 870 fuse_reply_err(req, ENOSYS); 871 } 872} 873 874static void do_access(fuse_req_t req, fuse_ino_t nodeid, 875 struct fuse_mbuf_iter *iter) 876{ 877 struct fuse_access_in *arg; 878 879 arg = fuse_mbuf_iter_advance(iter, sizeof(*arg)); 880 if (!arg) { 881 fuse_reply_err(req, EINVAL); 882 return; 883 } 884 885 if (req->se->op.access) { 886 req->se->op.access(req, nodeid, arg->mask); 887 } else { 888 fuse_reply_err(req, ENOSYS); 889 } 890} 891 892static void do_readlink(fuse_req_t req, fuse_ino_t nodeid, 893 struct fuse_mbuf_iter *iter) 894{ 895 (void)iter; 896 897 if (req->se->op.readlink) { 898 req->se->op.readlink(req, nodeid); 899 } else { 900 fuse_reply_err(req, ENOSYS); 901 } 902} 903 904static void do_mknod(fuse_req_t req, fuse_ino_t nodeid, 905 struct fuse_mbuf_iter *iter) 906{ 907 struct fuse_mknod_in *arg; 908 const char *name; 909 910 arg = fuse_mbuf_iter_advance(iter, sizeof(*arg)); 911 name = fuse_mbuf_iter_advance_str(iter); 912 if (!arg || !name) { 913 fuse_reply_err(req, EINVAL); 914 return; 915 } 916 917 req->ctx.umask = arg->umask; 918 919 if (req->se->op.mknod) { 920 req->se->op.mknod(req, nodeid, name, arg->mode, arg->rdev); 921 } else { 922 fuse_reply_err(req, ENOSYS); 923 } 924} 925 926static void do_mkdir(fuse_req_t req, fuse_ino_t nodeid, 927 struct fuse_mbuf_iter *iter) 928{ 929 struct fuse_mkdir_in *arg; 930 const char *name; 931 932 arg = fuse_mbuf_iter_advance(iter, sizeof(*arg)); 933 name = fuse_mbuf_iter_advance_str(iter); 934 if (!arg || !name) { 935 fuse_reply_err(req, EINVAL); 936 return; 937 } 938 939 req->ctx.umask = arg->umask; 940 941 if (req->se->op.mkdir) { 942 req->se->op.mkdir(req, nodeid, name, arg->mode); 943 } else { 944 fuse_reply_err(req, ENOSYS); 945 } 946} 947 948static void do_unlink(fuse_req_t req, fuse_ino_t nodeid, 949 struct fuse_mbuf_iter *iter) 950{ 951 const char *name = fuse_mbuf_iter_advance_str(iter); 952 953 if (!name) { 954 fuse_reply_err(req, EINVAL); 955 return; 956 } 957 958 if (req->se->op.unlink) { 959 req->se->op.unlink(req, nodeid, name); 960 } else { 961 fuse_reply_err(req, ENOSYS); 962 } 963} 964 965static void do_rmdir(fuse_req_t req, fuse_ino_t nodeid, 966 struct fuse_mbuf_iter *iter) 967{ 968 const char *name = fuse_mbuf_iter_advance_str(iter); 969 970 if (!name) { 971 fuse_reply_err(req, EINVAL); 972 return; 973 } 974 975 if (req->se->op.rmdir) { 976 req->se->op.rmdir(req, nodeid, name); 977 } else { 978 fuse_reply_err(req, ENOSYS); 979 } 980} 981 982static void do_symlink(fuse_req_t req, fuse_ino_t nodeid, 983 struct fuse_mbuf_iter *iter) 984{ 985 const char *name = fuse_mbuf_iter_advance_str(iter); 986 const char *linkname = fuse_mbuf_iter_advance_str(iter); 987 988 if (!name || !linkname) { 989 fuse_reply_err(req, EINVAL); 990 return; 991 } 992 993 if (req->se->op.symlink) { 994 req->se->op.symlink(req, linkname, nodeid, name); 995 } else { 996 fuse_reply_err(req, ENOSYS); 997 } 998} 999 1000static void do_rename(fuse_req_t req, fuse_ino_t nodeid, 1001 struct fuse_mbuf_iter *iter) 1002{ 1003 struct fuse_rename_in *arg; 1004 const char *oldname; 1005 const char *newname; 1006 1007 arg = fuse_mbuf_iter_advance(iter, sizeof(*arg)); 1008 oldname = fuse_mbuf_iter_advance_str(iter); 1009 newname = fuse_mbuf_iter_advance_str(iter); 1010 if (!arg || !oldname || !newname) { 1011 fuse_reply_err(req, EINVAL); 1012 return; 1013 } 1014 1015 if (req->se->op.rename) { 1016 req->se->op.rename(req, nodeid, oldname, arg->newdir, newname, 0); 1017 } else { 1018 fuse_reply_err(req, ENOSYS); 1019 } 1020} 1021 1022static void do_rename2(fuse_req_t req, fuse_ino_t nodeid, 1023 struct fuse_mbuf_iter *iter) 1024{ 1025 struct fuse_rename2_in *arg; 1026 const char *oldname; 1027 const char *newname; 1028 1029 arg = fuse_mbuf_iter_advance(iter, sizeof(*arg)); 1030 oldname = fuse_mbuf_iter_advance_str(iter); 1031 newname = fuse_mbuf_iter_advance_str(iter); 1032 if (!arg || !oldname || !newname) { 1033 fuse_reply_err(req, EINVAL); 1034 return; 1035 } 1036 1037 if (req->se->op.rename) { 1038 req->se->op.rename(req, nodeid, oldname, arg->newdir, newname, 1039 arg->flags); 1040 } else { 1041 fuse_reply_err(req, ENOSYS); 1042 } 1043} 1044 1045static void do_link(fuse_req_t req, fuse_ino_t nodeid, 1046 struct fuse_mbuf_iter *iter) 1047{ 1048 struct fuse_link_in *arg = fuse_mbuf_iter_advance(iter, sizeof(*arg)); 1049 const char *name = fuse_mbuf_iter_advance_str(iter); 1050 1051 if (!arg || !name) { 1052 fuse_reply_err(req, EINVAL); 1053 return; 1054 } 1055 1056 if (req->se->op.link) { 1057 req->se->op.link(req, arg->oldnodeid, nodeid, name); 1058 } else { 1059 fuse_reply_err(req, ENOSYS); 1060 } 1061} 1062 1063static void do_create(fuse_req_t req, fuse_ino_t nodeid, 1064 struct fuse_mbuf_iter *iter) 1065{ 1066 if (req->se->op.create) { 1067 struct fuse_create_in *arg; 1068 struct fuse_file_info fi; 1069 const char *name; 1070 1071 arg = fuse_mbuf_iter_advance(iter, sizeof(*arg)); 1072 name = fuse_mbuf_iter_advance_str(iter); 1073 if (!arg || !name) { 1074 fuse_reply_err(req, EINVAL); 1075 return; 1076 } 1077 1078 memset(&fi, 0, sizeof(fi)); 1079 fi.flags = arg->flags; 1080 1081 req->ctx.umask = arg->umask; 1082 1083 req->se->op.create(req, nodeid, name, arg->mode, &fi); 1084 } else { 1085 fuse_reply_err(req, ENOSYS); 1086 } 1087} 1088 1089static void do_open(fuse_req_t req, fuse_ino_t nodeid, 1090 struct fuse_mbuf_iter *iter) 1091{ 1092 struct fuse_open_in *arg; 1093 struct fuse_file_info fi; 1094 1095 arg = fuse_mbuf_iter_advance(iter, sizeof(*arg)); 1096 if (!arg) { 1097 fuse_reply_err(req, EINVAL); 1098 return; 1099 } 1100 1101 memset(&fi, 0, sizeof(fi)); 1102 fi.flags = arg->flags; 1103 1104 if (req->se->op.open) { 1105 req->se->op.open(req, nodeid, &fi); 1106 } else { 1107 fuse_reply_open(req, &fi); 1108 } 1109} 1110 1111static void do_read(fuse_req_t req, fuse_ino_t nodeid, 1112 struct fuse_mbuf_iter *iter) 1113{ 1114 if (req->se->op.read) { 1115 struct fuse_read_in *arg; 1116 struct fuse_file_info fi; 1117 1118 arg = fuse_mbuf_iter_advance(iter, sizeof(*arg)); 1119 if (!arg) { 1120 fuse_reply_err(req, EINVAL); 1121 return; 1122 } 1123 1124 memset(&fi, 0, sizeof(fi)); 1125 fi.fh = arg->fh; 1126 fi.lock_owner = arg->lock_owner; 1127 fi.flags = arg->flags; 1128 req->se->op.read(req, nodeid, arg->size, arg->offset, &fi); 1129 } else { 1130 fuse_reply_err(req, ENOSYS); 1131 } 1132} 1133 1134static void do_write(fuse_req_t req, fuse_ino_t nodeid, 1135 struct fuse_mbuf_iter *iter) 1136{ 1137 struct fuse_write_in *arg; 1138 struct fuse_file_info fi; 1139 const char *param; 1140 1141 arg = fuse_mbuf_iter_advance(iter, sizeof(*arg)); 1142 if (!arg) { 1143 fuse_reply_err(req, EINVAL); 1144 return; 1145 } 1146 1147 param = fuse_mbuf_iter_advance(iter, arg->size); 1148 if (!param) { 1149 fuse_reply_err(req, EINVAL); 1150 return; 1151 } 1152 1153 memset(&fi, 0, sizeof(fi)); 1154 fi.fh = arg->fh; 1155 fi.writepage = (arg->write_flags & FUSE_WRITE_CACHE) != 0; 1156 fi.kill_priv = !!(arg->write_flags & FUSE_WRITE_KILL_PRIV); 1157 1158 fi.lock_owner = arg->lock_owner; 1159 fi.flags = arg->flags; 1160 1161 if (req->se->op.write) { 1162 req->se->op.write(req, nodeid, param, arg->size, arg->offset, &fi); 1163 } else { 1164 fuse_reply_err(req, ENOSYS); 1165 } 1166} 1167 1168static void do_write_buf(fuse_req_t req, fuse_ino_t nodeid, 1169 struct fuse_mbuf_iter *iter, struct fuse_bufvec *ibufv) 1170{ 1171 struct fuse_session *se = req->se; 1172 struct fuse_bufvec *pbufv = ibufv; 1173 struct fuse_bufvec tmpbufv = { 1174 .buf[0] = ibufv->buf[0], 1175 .count = 1, 1176 }; 1177 struct fuse_write_in *arg; 1178 size_t arg_size = sizeof(*arg); 1179 struct fuse_file_info fi; 1180 1181 memset(&fi, 0, sizeof(fi)); 1182 1183 arg = fuse_mbuf_iter_advance(iter, arg_size); 1184 if (!arg) { 1185 fuse_reply_err(req, EINVAL); 1186 return; 1187 } 1188 1189 fi.lock_owner = arg->lock_owner; 1190 fi.flags = arg->flags; 1191 fi.fh = arg->fh; 1192 fi.writepage = !!(arg->write_flags & FUSE_WRITE_CACHE); 1193 fi.kill_priv = !!(arg->write_flags & FUSE_WRITE_KILL_PRIV); 1194 1195 if (ibufv->count == 1) { 1196 assert(!(tmpbufv.buf[0].flags & FUSE_BUF_IS_FD)); 1197 tmpbufv.buf[0].mem = ((char *)arg) + arg_size; 1198 tmpbufv.buf[0].size -= sizeof(struct fuse_in_header) + arg_size; 1199 pbufv = &tmpbufv; 1200 } else { 1201 /* 1202 * Input bufv contains the headers in the first element 1203 * and the data in the rest, we need to skip that first element 1204 */ 1205 ibufv->buf[0].size = 0; 1206 } 1207 1208 if (fuse_buf_size(pbufv) != arg->size) { 1209 fuse_log(FUSE_LOG_ERR, 1210 "fuse: do_write_buf: buffer size doesn't match arg->size\n"); 1211 fuse_reply_err(req, EIO); 1212 return; 1213 } 1214 1215 se->op.write_buf(req, nodeid, pbufv, arg->offset, &fi); 1216} 1217 1218static void do_flush(fuse_req_t req, fuse_ino_t nodeid, 1219 struct fuse_mbuf_iter *iter) 1220{ 1221 struct fuse_flush_in *arg; 1222 struct fuse_file_info fi; 1223 1224 arg = fuse_mbuf_iter_advance(iter, sizeof(*arg)); 1225 if (!arg) { 1226 fuse_reply_err(req, EINVAL); 1227 return; 1228 } 1229 1230 memset(&fi, 0, sizeof(fi)); 1231 fi.fh = arg->fh; 1232 fi.flush = 1; 1233 fi.lock_owner = arg->lock_owner; 1234 1235 if (req->se->op.flush) { 1236 req->se->op.flush(req, nodeid, &fi); 1237 } else { 1238 fuse_reply_err(req, ENOSYS); 1239 } 1240} 1241 1242static void do_release(fuse_req_t req, fuse_ino_t nodeid, 1243 struct fuse_mbuf_iter *iter) 1244{ 1245 struct fuse_release_in *arg; 1246 struct fuse_file_info fi; 1247 1248 arg = fuse_mbuf_iter_advance(iter, sizeof(*arg)); 1249 if (!arg) { 1250 fuse_reply_err(req, EINVAL); 1251 return; 1252 } 1253 1254 memset(&fi, 0, sizeof(fi)); 1255 fi.flags = arg->flags; 1256 fi.fh = arg->fh; 1257 fi.flush = (arg->release_flags & FUSE_RELEASE_FLUSH) ? 1 : 0; 1258 fi.lock_owner = arg->lock_owner; 1259 1260 if (arg->release_flags & FUSE_RELEASE_FLOCK_UNLOCK) { 1261 fi.flock_release = 1; 1262 } 1263 1264 if (req->se->op.release) { 1265 req->se->op.release(req, nodeid, &fi); 1266 } else { 1267 fuse_reply_err(req, 0); 1268 } 1269} 1270 1271static void do_fsync(fuse_req_t req, fuse_ino_t nodeid, 1272 struct fuse_mbuf_iter *iter) 1273{ 1274 struct fuse_fsync_in *arg; 1275 struct fuse_file_info fi; 1276 int datasync; 1277 1278 arg = fuse_mbuf_iter_advance(iter, sizeof(*arg)); 1279 if (!arg) { 1280 fuse_reply_err(req, EINVAL); 1281 return; 1282 } 1283 datasync = arg->fsync_flags & 1; 1284 1285 memset(&fi, 0, sizeof(fi)); 1286 fi.fh = arg->fh; 1287 1288 if (req->se->op.fsync) { 1289 if (fi.fh == (uint64_t)-1) { 1290 req->se->op.fsync(req, nodeid, datasync, NULL); 1291 } else { 1292 req->se->op.fsync(req, nodeid, datasync, &fi); 1293 } 1294 } else { 1295 fuse_reply_err(req, ENOSYS); 1296 } 1297} 1298 1299static void do_opendir(fuse_req_t req, fuse_ino_t nodeid, 1300 struct fuse_mbuf_iter *iter) 1301{ 1302 struct fuse_open_in *arg; 1303 struct fuse_file_info fi; 1304 1305 arg = fuse_mbuf_iter_advance(iter, sizeof(*arg)); 1306 if (!arg) { 1307 fuse_reply_err(req, EINVAL); 1308 return; 1309 } 1310 1311 memset(&fi, 0, sizeof(fi)); 1312 fi.flags = arg->flags; 1313 1314 if (req->se->op.opendir) { 1315 req->se->op.opendir(req, nodeid, &fi); 1316 } else { 1317 fuse_reply_open(req, &fi); 1318 } 1319} 1320 1321static void do_readdir(fuse_req_t req, fuse_ino_t nodeid, 1322 struct fuse_mbuf_iter *iter) 1323{ 1324 struct fuse_read_in *arg; 1325 struct fuse_file_info fi; 1326 1327 arg = fuse_mbuf_iter_advance(iter, sizeof(*arg)); 1328 if (!arg) { 1329 fuse_reply_err(req, EINVAL); 1330 return; 1331 } 1332 1333 memset(&fi, 0, sizeof(fi)); 1334 fi.fh = arg->fh; 1335 1336 if (req->se->op.readdir) { 1337 req->se->op.readdir(req, nodeid, arg->size, arg->offset, &fi); 1338 } else { 1339 fuse_reply_err(req, ENOSYS); 1340 } 1341} 1342 1343static void do_readdirplus(fuse_req_t req, fuse_ino_t nodeid, 1344 struct fuse_mbuf_iter *iter) 1345{ 1346 struct fuse_read_in *arg; 1347 struct fuse_file_info fi; 1348 1349 arg = fuse_mbuf_iter_advance(iter, sizeof(*arg)); 1350 if (!arg) { 1351 fuse_reply_err(req, EINVAL); 1352 return; 1353 } 1354 1355 memset(&fi, 0, sizeof(fi)); 1356 fi.fh = arg->fh; 1357 1358 if (req->se->op.readdirplus) { 1359 req->se->op.readdirplus(req, nodeid, arg->size, arg->offset, &fi); 1360 } else { 1361 fuse_reply_err(req, ENOSYS); 1362 } 1363} 1364 1365static void do_releasedir(fuse_req_t req, fuse_ino_t nodeid, 1366 struct fuse_mbuf_iter *iter) 1367{ 1368 struct fuse_release_in *arg; 1369 struct fuse_file_info fi; 1370 1371 arg = fuse_mbuf_iter_advance(iter, sizeof(*arg)); 1372 if (!arg) { 1373 fuse_reply_err(req, EINVAL); 1374 return; 1375 } 1376 1377 memset(&fi, 0, sizeof(fi)); 1378 fi.flags = arg->flags; 1379 fi.fh = arg->fh; 1380 1381 if (req->se->op.releasedir) { 1382 req->se->op.releasedir(req, nodeid, &fi); 1383 } else { 1384 fuse_reply_err(req, 0); 1385 } 1386} 1387 1388static void do_fsyncdir(fuse_req_t req, fuse_ino_t nodeid, 1389 struct fuse_mbuf_iter *iter) 1390{ 1391 struct fuse_fsync_in *arg; 1392 struct fuse_file_info fi; 1393 int datasync; 1394 1395 arg = fuse_mbuf_iter_advance(iter, sizeof(*arg)); 1396 if (!arg) { 1397 fuse_reply_err(req, EINVAL); 1398 return; 1399 } 1400 datasync = arg->fsync_flags & 1; 1401 1402 memset(&fi, 0, sizeof(fi)); 1403 fi.fh = arg->fh; 1404 1405 if (req->se->op.fsyncdir) { 1406 req->se->op.fsyncdir(req, nodeid, datasync, &fi); 1407 } else { 1408 fuse_reply_err(req, ENOSYS); 1409 } 1410} 1411 1412static void do_statfs(fuse_req_t req, fuse_ino_t nodeid, 1413 struct fuse_mbuf_iter *iter) 1414{ 1415 (void)nodeid; 1416 (void)iter; 1417 1418 if (req->se->op.statfs) { 1419 req->se->op.statfs(req, nodeid); 1420 } else { 1421 struct statvfs buf = { 1422 .f_namemax = 255, 1423 .f_bsize = 512, 1424 }; 1425 fuse_reply_statfs(req, &buf); 1426 } 1427} 1428 1429static void do_setxattr(fuse_req_t req, fuse_ino_t nodeid, 1430 struct fuse_mbuf_iter *iter) 1431{ 1432 struct fuse_setxattr_in *arg; 1433 const char *name; 1434 const char *value; 1435 1436 arg = fuse_mbuf_iter_advance(iter, sizeof(*arg)); 1437 name = fuse_mbuf_iter_advance_str(iter); 1438 if (!arg || !name) { 1439 fuse_reply_err(req, EINVAL); 1440 return; 1441 } 1442 1443 value = fuse_mbuf_iter_advance(iter, arg->size); 1444 if (!value) { 1445 fuse_reply_err(req, EINVAL); 1446 return; 1447 } 1448 1449 if (req->se->op.setxattr) { 1450 req->se->op.setxattr(req, nodeid, name, value, arg->size, arg->flags); 1451 } else { 1452 fuse_reply_err(req, ENOSYS); 1453 } 1454} 1455 1456static void do_getxattr(fuse_req_t req, fuse_ino_t nodeid, 1457 struct fuse_mbuf_iter *iter) 1458{ 1459 struct fuse_getxattr_in *arg; 1460 const char *name; 1461 1462 arg = fuse_mbuf_iter_advance(iter, sizeof(*arg)); 1463 name = fuse_mbuf_iter_advance_str(iter); 1464 if (!arg || !name) { 1465 fuse_reply_err(req, EINVAL); 1466 return; 1467 } 1468 1469 if (req->se->op.getxattr) { 1470 req->se->op.getxattr(req, nodeid, name, arg->size); 1471 } else { 1472 fuse_reply_err(req, ENOSYS); 1473 } 1474} 1475 1476static void do_listxattr(fuse_req_t req, fuse_ino_t nodeid, 1477 struct fuse_mbuf_iter *iter) 1478{ 1479 struct fuse_getxattr_in *arg; 1480 1481 arg = fuse_mbuf_iter_advance(iter, sizeof(*arg)); 1482 if (!arg) { 1483 fuse_reply_err(req, EINVAL); 1484 return; 1485 } 1486 1487 if (req->se->op.listxattr) { 1488 req->se->op.listxattr(req, nodeid, arg->size); 1489 } else { 1490 fuse_reply_err(req, ENOSYS); 1491 } 1492} 1493 1494static void do_removexattr(fuse_req_t req, fuse_ino_t nodeid, 1495 struct fuse_mbuf_iter *iter) 1496{ 1497 const char *name = fuse_mbuf_iter_advance_str(iter); 1498 1499 if (!name) { 1500 fuse_reply_err(req, EINVAL); 1501 return; 1502 } 1503 1504 if (req->se->op.removexattr) { 1505 req->se->op.removexattr(req, nodeid, name); 1506 } else { 1507 fuse_reply_err(req, ENOSYS); 1508 } 1509} 1510 1511static void convert_fuse_file_lock(struct fuse_file_lock *fl, 1512 struct flock *flock) 1513{ 1514 memset(flock, 0, sizeof(struct flock)); 1515 flock->l_type = fl->type; 1516 flock->l_whence = SEEK_SET; 1517 flock->l_start = fl->start; 1518 if (fl->end == OFFSET_MAX) { 1519 flock->l_len = 0; 1520 } else { 1521 flock->l_len = fl->end - fl->start + 1; 1522 } 1523 flock->l_pid = fl->pid; 1524} 1525 1526static void do_getlk(fuse_req_t req, fuse_ino_t nodeid, 1527 struct fuse_mbuf_iter *iter) 1528{ 1529 struct fuse_lk_in *arg; 1530 struct fuse_file_info fi; 1531 struct flock flock; 1532 1533 arg = fuse_mbuf_iter_advance(iter, sizeof(*arg)); 1534 if (!arg) { 1535 fuse_reply_err(req, EINVAL); 1536 return; 1537 } 1538 1539 memset(&fi, 0, sizeof(fi)); 1540 fi.fh = arg->fh; 1541 fi.lock_owner = arg->owner; 1542 1543 convert_fuse_file_lock(&arg->lk, &flock); 1544 if (req->se->op.getlk) { 1545 req->se->op.getlk(req, nodeid, &fi, &flock); 1546 } else { 1547 fuse_reply_err(req, ENOSYS); 1548 } 1549} 1550 1551static void do_setlk_common(fuse_req_t req, fuse_ino_t nodeid, 1552 struct fuse_mbuf_iter *iter, int sleep) 1553{ 1554 struct fuse_lk_in *arg; 1555 struct fuse_file_info fi; 1556 struct flock flock; 1557 1558 arg = fuse_mbuf_iter_advance(iter, sizeof(*arg)); 1559 if (!arg) { 1560 fuse_reply_err(req, EINVAL); 1561 return; 1562 } 1563 1564 memset(&fi, 0, sizeof(fi)); 1565 fi.fh = arg->fh; 1566 fi.lock_owner = arg->owner; 1567 1568 if (arg->lk_flags & FUSE_LK_FLOCK) { 1569 int op = 0; 1570 1571 switch (arg->lk.type) { 1572 case F_RDLCK: 1573 op = LOCK_SH; 1574 break; 1575 case F_WRLCK: 1576 op = LOCK_EX; 1577 break; 1578 case F_UNLCK: 1579 op = LOCK_UN; 1580 break; 1581 } 1582 if (!sleep) { 1583 op |= LOCK_NB; 1584 } 1585 1586 if (req->se->op.flock) { 1587 req->se->op.flock(req, nodeid, &fi, op); 1588 } else { 1589 fuse_reply_err(req, ENOSYS); 1590 } 1591 } else { 1592 convert_fuse_file_lock(&arg->lk, &flock); 1593 if (req->se->op.setlk) { 1594 req->se->op.setlk(req, nodeid, &fi, &flock, sleep); 1595 } else { 1596 fuse_reply_err(req, ENOSYS); 1597 } 1598 } 1599} 1600 1601static void do_setlk(fuse_req_t req, fuse_ino_t nodeid, 1602 struct fuse_mbuf_iter *iter) 1603{ 1604 do_setlk_common(req, nodeid, iter, 0); 1605} 1606 1607static void do_setlkw(fuse_req_t req, fuse_ino_t nodeid, 1608 struct fuse_mbuf_iter *iter) 1609{ 1610 do_setlk_common(req, nodeid, iter, 1); 1611} 1612 1613static int find_interrupted(struct fuse_session *se, struct fuse_req *req) 1614{ 1615 struct fuse_req *curr; 1616 1617 for (curr = se->list.next; curr != &se->list; curr = curr->next) { 1618 if (curr->unique == req->u.i.unique) { 1619 fuse_interrupt_func_t func; 1620 void *data; 1621 1622 curr->ctr++; 1623 pthread_mutex_unlock(&se->lock); 1624 1625 /* Ugh, ugly locking */ 1626 pthread_mutex_lock(&curr->lock); 1627 pthread_mutex_lock(&se->lock); 1628 curr->interrupted = 1; 1629 func = curr->u.ni.func; 1630 data = curr->u.ni.data; 1631 pthread_mutex_unlock(&se->lock); 1632 if (func) { 1633 func(curr, data); 1634 } 1635 pthread_mutex_unlock(&curr->lock); 1636 1637 pthread_mutex_lock(&se->lock); 1638 curr->ctr--; 1639 if (!curr->ctr) { 1640 destroy_req(curr); 1641 } 1642 1643 return 1; 1644 } 1645 } 1646 for (curr = se->interrupts.next; curr != &se->interrupts; 1647 curr = curr->next) { 1648 if (curr->u.i.unique == req->u.i.unique) { 1649 return 1; 1650 } 1651 } 1652 return 0; 1653} 1654 1655static void do_interrupt(fuse_req_t req, fuse_ino_t nodeid, 1656 struct fuse_mbuf_iter *iter) 1657{ 1658 struct fuse_interrupt_in *arg; 1659 struct fuse_session *se = req->se; 1660 1661 (void)nodeid; 1662 1663 arg = fuse_mbuf_iter_advance(iter, sizeof(*arg)); 1664 if (!arg) { 1665 fuse_reply_err(req, EINVAL); 1666 return; 1667 } 1668 1669 fuse_log(FUSE_LOG_DEBUG, "INTERRUPT: %llu\n", 1670 (unsigned long long)arg->unique); 1671 1672 req->u.i.unique = arg->unique; 1673 1674 pthread_mutex_lock(&se->lock); 1675 if (find_interrupted(se, req)) { 1676 destroy_req(req); 1677 } else { 1678 list_add_req(req, &se->interrupts); 1679 } 1680 pthread_mutex_unlock(&se->lock); 1681} 1682 1683static struct fuse_req *check_interrupt(struct fuse_session *se, 1684 struct fuse_req *req) 1685{ 1686 struct fuse_req *curr; 1687 1688 for (curr = se->interrupts.next; curr != &se->interrupts; 1689 curr = curr->next) { 1690 if (curr->u.i.unique == req->unique) { 1691 req->interrupted = 1; 1692 list_del_req(curr); 1693 free(curr); 1694 return NULL; 1695 } 1696 } 1697 curr = se->interrupts.next; 1698 if (curr != &se->interrupts) { 1699 list_del_req(curr); 1700 list_init_req(curr); 1701 return curr; 1702 } else { 1703 return NULL; 1704 } 1705} 1706 1707static void do_bmap(fuse_req_t req, fuse_ino_t nodeid, 1708 struct fuse_mbuf_iter *iter) 1709{ 1710 struct fuse_bmap_in *arg = fuse_mbuf_iter_advance(iter, sizeof(*arg)); 1711 1712 if (!arg) { 1713 fuse_reply_err(req, EINVAL); 1714 return; 1715 } 1716 1717 if (req->se->op.bmap) { 1718 req->se->op.bmap(req, nodeid, arg->blocksize, arg->block); 1719 } else { 1720 fuse_reply_err(req, ENOSYS); 1721 } 1722} 1723 1724static void do_ioctl(fuse_req_t req, fuse_ino_t nodeid, 1725 struct fuse_mbuf_iter *iter) 1726{ 1727 struct fuse_ioctl_in *arg; 1728 unsigned int flags; 1729 void *in_buf = NULL; 1730 struct fuse_file_info fi; 1731 1732 arg = fuse_mbuf_iter_advance(iter, sizeof(*arg)); 1733 if (!arg) { 1734 fuse_reply_err(req, EINVAL); 1735 return; 1736 } 1737 1738 flags = arg->flags; 1739 if (flags & FUSE_IOCTL_DIR && !(req->se->conn.want & FUSE_CAP_IOCTL_DIR)) { 1740 fuse_reply_err(req, ENOTTY); 1741 return; 1742 } 1743 1744 if (arg->in_size) { 1745 in_buf = fuse_mbuf_iter_advance(iter, arg->in_size); 1746 if (!in_buf) { 1747 fuse_reply_err(req, EINVAL); 1748 return; 1749 } 1750 } 1751 1752 memset(&fi, 0, sizeof(fi)); 1753 fi.fh = arg->fh; 1754 1755 if (sizeof(void *) == 4 && !(flags & FUSE_IOCTL_32BIT)) { 1756 req->ioctl_64bit = 1; 1757 } 1758 1759 if (req->se->op.ioctl) { 1760 req->se->op.ioctl(req, nodeid, arg->cmd, (void *)(uintptr_t)arg->arg, 1761 &fi, flags, in_buf, arg->in_size, arg->out_size); 1762 } else { 1763 fuse_reply_err(req, ENOSYS); 1764 } 1765} 1766 1767void fuse_pollhandle_destroy(struct fuse_pollhandle *ph) 1768{ 1769 free(ph); 1770} 1771 1772static void do_poll(fuse_req_t req, fuse_ino_t nodeid, 1773 struct fuse_mbuf_iter *iter) 1774{ 1775 struct fuse_poll_in *arg; 1776 struct fuse_file_info fi; 1777 1778 arg = fuse_mbuf_iter_advance(iter, sizeof(*arg)); 1779 if (!arg) { 1780 fuse_reply_err(req, EINVAL); 1781 return; 1782 } 1783 1784 memset(&fi, 0, sizeof(fi)); 1785 fi.fh = arg->fh; 1786 fi.poll_events = arg->events; 1787 1788 if (req->se->op.poll) { 1789 struct fuse_pollhandle *ph = NULL; 1790 1791 if (arg->flags & FUSE_POLL_SCHEDULE_NOTIFY) { 1792 ph = malloc(sizeof(struct fuse_pollhandle)); 1793 if (ph == NULL) { 1794 fuse_reply_err(req, ENOMEM); 1795 return; 1796 } 1797 ph->kh = arg->kh; 1798 ph->se = req->se; 1799 } 1800 1801 req->se->op.poll(req, nodeid, &fi, ph); 1802 } else { 1803 fuse_reply_err(req, ENOSYS); 1804 } 1805} 1806 1807static void do_fallocate(fuse_req_t req, fuse_ino_t nodeid, 1808 struct fuse_mbuf_iter *iter) 1809{ 1810 struct fuse_fallocate_in *arg; 1811 struct fuse_file_info fi; 1812 1813 arg = fuse_mbuf_iter_advance(iter, sizeof(*arg)); 1814 if (!arg) { 1815 fuse_reply_err(req, EINVAL); 1816 return; 1817 } 1818 1819 memset(&fi, 0, sizeof(fi)); 1820 fi.fh = arg->fh; 1821 1822 if (req->se->op.fallocate) { 1823 req->se->op.fallocate(req, nodeid, arg->mode, arg->offset, arg->length, 1824 &fi); 1825 } else { 1826 fuse_reply_err(req, ENOSYS); 1827 } 1828} 1829 1830static void do_copy_file_range(fuse_req_t req, fuse_ino_t nodeid_in, 1831 struct fuse_mbuf_iter *iter) 1832{ 1833 struct fuse_copy_file_range_in *arg; 1834 struct fuse_file_info fi_in, fi_out; 1835 1836 arg = fuse_mbuf_iter_advance(iter, sizeof(*arg)); 1837 if (!arg) { 1838 fuse_reply_err(req, EINVAL); 1839 return; 1840 } 1841 1842 memset(&fi_in, 0, sizeof(fi_in)); 1843 fi_in.fh = arg->fh_in; 1844 1845 memset(&fi_out, 0, sizeof(fi_out)); 1846 fi_out.fh = arg->fh_out; 1847 1848 1849 if (req->se->op.copy_file_range) { 1850 req->se->op.copy_file_range(req, nodeid_in, arg->off_in, &fi_in, 1851 arg->nodeid_out, arg->off_out, &fi_out, 1852 arg->len, arg->flags); 1853 } else { 1854 fuse_reply_err(req, ENOSYS); 1855 } 1856} 1857 1858static void do_lseek(fuse_req_t req, fuse_ino_t nodeid, 1859 struct fuse_mbuf_iter *iter) 1860{ 1861 struct fuse_lseek_in *arg; 1862 struct fuse_file_info fi; 1863 1864 arg = fuse_mbuf_iter_advance(iter, sizeof(*arg)); 1865 if (!arg) { 1866 fuse_reply_err(req, EINVAL); 1867 return; 1868 } 1869 memset(&fi, 0, sizeof(fi)); 1870 fi.fh = arg->fh; 1871 1872 if (req->se->op.lseek) { 1873 req->se->op.lseek(req, nodeid, arg->offset, arg->whence, &fi); 1874 } else { 1875 fuse_reply_err(req, ENOSYS); 1876 } 1877} 1878 1879static void do_init(fuse_req_t req, fuse_ino_t nodeid, 1880 struct fuse_mbuf_iter *iter) 1881{ 1882 size_t compat_size = offsetof(struct fuse_init_in, max_readahead); 1883 struct fuse_init_in *arg; 1884 struct fuse_init_out outarg; 1885 struct fuse_session *se = req->se; 1886 size_t bufsize = se->bufsize; 1887 size_t outargsize = sizeof(outarg); 1888 1889 (void)nodeid; 1890 1891 /* First consume the old fields... */ 1892 arg = fuse_mbuf_iter_advance(iter, compat_size); 1893 if (!arg) { 1894 fuse_reply_err(req, EINVAL); 1895 return; 1896 } 1897 1898 /* ...and now consume the new fields. */ 1899 if (arg->major == 7 && arg->minor >= 6) { 1900 if (!fuse_mbuf_iter_advance(iter, sizeof(*arg) - compat_size)) { 1901 fuse_reply_err(req, EINVAL); 1902 return; 1903 } 1904 } 1905 1906 fuse_log(FUSE_LOG_DEBUG, "INIT: %u.%u\n", arg->major, arg->minor); 1907 if (arg->major == 7 && arg->minor >= 6) { 1908 fuse_log(FUSE_LOG_DEBUG, "flags=0x%08x\n", arg->flags); 1909 fuse_log(FUSE_LOG_DEBUG, "max_readahead=0x%08x\n", arg->max_readahead); 1910 } 1911 se->conn.proto_major = arg->major; 1912 se->conn.proto_minor = arg->minor; 1913 se->conn.capable = 0; 1914 se->conn.want = 0; 1915 1916 memset(&outarg, 0, sizeof(outarg)); 1917 outarg.major = FUSE_KERNEL_VERSION; 1918 outarg.minor = FUSE_KERNEL_MINOR_VERSION; 1919 1920 if (arg->major < 7 || (arg->major == 7 && arg->minor < 31)) { 1921 fuse_log(FUSE_LOG_ERR, "fuse: unsupported protocol version: %u.%u\n", 1922 arg->major, arg->minor); 1923 fuse_reply_err(req, EPROTO); 1924 return; 1925 } 1926 1927 if (arg->major > 7) { 1928 /* Wait for a second INIT request with a 7.X version */ 1929 send_reply_ok(req, &outarg, sizeof(outarg)); 1930 return; 1931 } 1932 1933 if (arg->max_readahead < se->conn.max_readahead) { 1934 se->conn.max_readahead = arg->max_readahead; 1935 } 1936 if (arg->flags & FUSE_ASYNC_READ) { 1937 se->conn.capable |= FUSE_CAP_ASYNC_READ; 1938 } 1939 if (arg->flags & FUSE_POSIX_LOCKS) { 1940 se->conn.capable |= FUSE_CAP_POSIX_LOCKS; 1941 } 1942 if (arg->flags & FUSE_ATOMIC_O_TRUNC) { 1943 se->conn.capable |= FUSE_CAP_ATOMIC_O_TRUNC; 1944 } 1945 if (arg->flags & FUSE_EXPORT_SUPPORT) { 1946 se->conn.capable |= FUSE_CAP_EXPORT_SUPPORT; 1947 } 1948 if (arg->flags & FUSE_DONT_MASK) { 1949 se->conn.capable |= FUSE_CAP_DONT_MASK; 1950 } 1951 if (arg->flags & FUSE_FLOCK_LOCKS) { 1952 se->conn.capable |= FUSE_CAP_FLOCK_LOCKS; 1953 } 1954 if (arg->flags & FUSE_AUTO_INVAL_DATA) { 1955 se->conn.capable |= FUSE_CAP_AUTO_INVAL_DATA; 1956 } 1957 if (arg->flags & FUSE_DO_READDIRPLUS) { 1958 se->conn.capable |= FUSE_CAP_READDIRPLUS; 1959 } 1960 if (arg->flags & FUSE_READDIRPLUS_AUTO) { 1961 se->conn.capable |= FUSE_CAP_READDIRPLUS_AUTO; 1962 } 1963 if (arg->flags & FUSE_ASYNC_DIO) { 1964 se->conn.capable |= FUSE_CAP_ASYNC_DIO; 1965 } 1966 if (arg->flags & FUSE_WRITEBACK_CACHE) { 1967 se->conn.capable |= FUSE_CAP_WRITEBACK_CACHE; 1968 } 1969 if (arg->flags & FUSE_NO_OPEN_SUPPORT) { 1970 se->conn.capable |= FUSE_CAP_NO_OPEN_SUPPORT; 1971 } 1972 if (arg->flags & FUSE_PARALLEL_DIROPS) { 1973 se->conn.capable |= FUSE_CAP_PARALLEL_DIROPS; 1974 } 1975 if (arg->flags & FUSE_POSIX_ACL) { 1976 se->conn.capable |= FUSE_CAP_POSIX_ACL; 1977 } 1978 if (arg->flags & FUSE_HANDLE_KILLPRIV) { 1979 se->conn.capable |= FUSE_CAP_HANDLE_KILLPRIV; 1980 } 1981 if (arg->flags & FUSE_NO_OPENDIR_SUPPORT) { 1982 se->conn.capable |= FUSE_CAP_NO_OPENDIR_SUPPORT; 1983 } 1984 if (!(arg->flags & FUSE_MAX_PAGES)) { 1985 size_t max_bufsize = FUSE_DEFAULT_MAX_PAGES_PER_REQ * getpagesize() + 1986 FUSE_BUFFER_HEADER_SIZE; 1987 if (bufsize > max_bufsize) { 1988 bufsize = max_bufsize; 1989 } 1990 } 1991#ifdef HAVE_SPLICE 1992#ifdef HAVE_VMSPLICE 1993 se->conn.capable |= FUSE_CAP_SPLICE_WRITE | FUSE_CAP_SPLICE_MOVE; 1994#endif 1995 se->conn.capable |= FUSE_CAP_SPLICE_READ; 1996#endif 1997 se->conn.capable |= FUSE_CAP_IOCTL_DIR; 1998 1999 /* 2000 * Default settings for modern filesystems. 2001 * 2002 * Most of these capabilities were disabled by default in 2003 * libfuse2 for backwards compatibility reasons. In libfuse3, 2004 * we can finally enable them by default (as long as they're 2005 * supported by the kernel). 2006 */ 2007#define LL_SET_DEFAULT(cond, cap) \ 2008 if ((cond) && (se->conn.capable & (cap))) \ 2009 se->conn.want |= (cap) 2010 LL_SET_DEFAULT(1, FUSE_CAP_ASYNC_READ); 2011 LL_SET_DEFAULT(1, FUSE_CAP_PARALLEL_DIROPS); 2012 LL_SET_DEFAULT(1, FUSE_CAP_AUTO_INVAL_DATA); 2013 LL_SET_DEFAULT(1, FUSE_CAP_HANDLE_KILLPRIV); 2014 LL_SET_DEFAULT(1, FUSE_CAP_ASYNC_DIO); 2015 LL_SET_DEFAULT(1, FUSE_CAP_IOCTL_DIR); 2016 LL_SET_DEFAULT(1, FUSE_CAP_ATOMIC_O_TRUNC); 2017 LL_SET_DEFAULT(se->op.write_buf, FUSE_CAP_SPLICE_READ); 2018 LL_SET_DEFAULT(se->op.getlk && se->op.setlk, FUSE_CAP_POSIX_LOCKS); 2019 LL_SET_DEFAULT(se->op.flock, FUSE_CAP_FLOCK_LOCKS); 2020 LL_SET_DEFAULT(se->op.readdirplus, FUSE_CAP_READDIRPLUS); 2021 LL_SET_DEFAULT(se->op.readdirplus && se->op.readdir, 2022 FUSE_CAP_READDIRPLUS_AUTO); 2023 se->conn.time_gran = 1; 2024 2025 if (bufsize < FUSE_MIN_READ_BUFFER) { 2026 fuse_log(FUSE_LOG_ERR, "fuse: warning: buffer size too small: %zu\n", 2027 bufsize); 2028 bufsize = FUSE_MIN_READ_BUFFER; 2029 } 2030 se->bufsize = bufsize; 2031 2032 if (se->conn.max_write > bufsize - FUSE_BUFFER_HEADER_SIZE) { 2033 se->conn.max_write = bufsize - FUSE_BUFFER_HEADER_SIZE; 2034 } 2035 2036 se->got_init = 1; 2037 se->got_destroy = 0; 2038 if (se->op.init) { 2039 se->op.init(se->userdata, &se->conn); 2040 } 2041 2042 if (se->conn.want & (~se->conn.capable)) { 2043 fuse_log(FUSE_LOG_ERR, 2044 "fuse: error: filesystem requested capabilities " 2045 "0x%x that are not supported by kernel, aborting.\n", 2046 se->conn.want & (~se->conn.capable)); 2047 fuse_reply_err(req, EPROTO); 2048 se->error = -EPROTO; 2049 fuse_session_exit(se); 2050 return; 2051 } 2052 2053 if (se->conn.max_write < bufsize - FUSE_BUFFER_HEADER_SIZE) { 2054 se->bufsize = se->conn.max_write + FUSE_BUFFER_HEADER_SIZE; 2055 } 2056 if (arg->flags & FUSE_MAX_PAGES) { 2057 outarg.flags |= FUSE_MAX_PAGES; 2058 outarg.max_pages = (se->conn.max_write - 1) / getpagesize() + 1; 2059 } 2060 2061 /* 2062 * Always enable big writes, this is superseded 2063 * by the max_write option 2064 */ 2065 outarg.flags |= FUSE_BIG_WRITES; 2066 2067 if (se->conn.want & FUSE_CAP_ASYNC_READ) { 2068 outarg.flags |= FUSE_ASYNC_READ; 2069 } 2070 if (se->conn.want & FUSE_CAP_PARALLEL_DIROPS) { 2071 outarg.flags |= FUSE_PARALLEL_DIROPS; 2072 } 2073 if (se->conn.want & FUSE_CAP_POSIX_LOCKS) { 2074 outarg.flags |= FUSE_POSIX_LOCKS; 2075 } 2076 if (se->conn.want & FUSE_CAP_ATOMIC_O_TRUNC) { 2077 outarg.flags |= FUSE_ATOMIC_O_TRUNC; 2078 } 2079 if (se->conn.want & FUSE_CAP_EXPORT_SUPPORT) { 2080 outarg.flags |= FUSE_EXPORT_SUPPORT; 2081 } 2082 if (se->conn.want & FUSE_CAP_DONT_MASK) { 2083 outarg.flags |= FUSE_DONT_MASK; 2084 } 2085 if (se->conn.want & FUSE_CAP_FLOCK_LOCKS) { 2086 outarg.flags |= FUSE_FLOCK_LOCKS; 2087 } 2088 if (se->conn.want & FUSE_CAP_AUTO_INVAL_DATA) { 2089 outarg.flags |= FUSE_AUTO_INVAL_DATA; 2090 } 2091 if (se->conn.want & FUSE_CAP_READDIRPLUS) { 2092 outarg.flags |= FUSE_DO_READDIRPLUS; 2093 } 2094 if (se->conn.want & FUSE_CAP_READDIRPLUS_AUTO) { 2095 outarg.flags |= FUSE_READDIRPLUS_AUTO; 2096 } 2097 if (se->conn.want & FUSE_CAP_ASYNC_DIO) { 2098 outarg.flags |= FUSE_ASYNC_DIO; 2099 } 2100 if (se->conn.want & FUSE_CAP_WRITEBACK_CACHE) { 2101 outarg.flags |= FUSE_WRITEBACK_CACHE; 2102 } 2103 if (se->conn.want & FUSE_CAP_POSIX_ACL) { 2104 outarg.flags |= FUSE_POSIX_ACL; 2105 } 2106 outarg.max_readahead = se->conn.max_readahead; 2107 outarg.max_write = se->conn.max_write; 2108 if (se->conn.max_background >= (1 << 16)) { 2109 se->conn.max_background = (1 << 16) - 1; 2110 } 2111 if (se->conn.congestion_threshold > se->conn.max_background) { 2112 se->conn.congestion_threshold = se->conn.max_background; 2113 } 2114 if (!se->conn.congestion_threshold) { 2115 se->conn.congestion_threshold = se->conn.max_background * 3 / 4; 2116 } 2117 2118 outarg.max_background = se->conn.max_background; 2119 outarg.congestion_threshold = se->conn.congestion_threshold; 2120 outarg.time_gran = se->conn.time_gran; 2121 2122 fuse_log(FUSE_LOG_DEBUG, " INIT: %u.%u\n", outarg.major, outarg.minor); 2123 fuse_log(FUSE_LOG_DEBUG, " flags=0x%08x\n", outarg.flags); 2124 fuse_log(FUSE_LOG_DEBUG, " max_readahead=0x%08x\n", outarg.max_readahead); 2125 fuse_log(FUSE_LOG_DEBUG, " max_write=0x%08x\n", outarg.max_write); 2126 fuse_log(FUSE_LOG_DEBUG, " max_background=%i\n", outarg.max_background); 2127 fuse_log(FUSE_LOG_DEBUG, " congestion_threshold=%i\n", 2128 outarg.congestion_threshold); 2129 fuse_log(FUSE_LOG_DEBUG, " time_gran=%u\n", outarg.time_gran); 2130 2131 send_reply_ok(req, &outarg, outargsize); 2132} 2133 2134static void do_destroy(fuse_req_t req, fuse_ino_t nodeid, 2135 struct fuse_mbuf_iter *iter) 2136{ 2137 struct fuse_session *se = req->se; 2138 2139 (void)nodeid; 2140 (void)iter; 2141 2142 se->got_destroy = 1; 2143 se->got_init = 0; 2144 if (se->op.destroy) { 2145 se->op.destroy(se->userdata); 2146 } 2147 2148 send_reply_ok(req, NULL, 0); 2149} 2150 2151static int send_notify_iov(struct fuse_session *se, int notify_code, 2152 struct iovec *iov, int count) 2153{ 2154 struct fuse_out_header out = { 2155 .error = notify_code, 2156 }; 2157 2158 if (!se->got_init) { 2159 return -ENOTCONN; 2160 } 2161 2162 iov[0].iov_base = &out; 2163 iov[0].iov_len = sizeof(struct fuse_out_header); 2164 2165 return fuse_send_msg(se, NULL, iov, count); 2166} 2167 2168int fuse_lowlevel_notify_poll(struct fuse_pollhandle *ph) 2169{ 2170 if (ph != NULL) { 2171 struct fuse_notify_poll_wakeup_out outarg = { 2172 .kh = ph->kh, 2173 }; 2174 struct iovec iov[2]; 2175 2176 iov[1].iov_base = &outarg; 2177 iov[1].iov_len = sizeof(outarg); 2178 2179 return send_notify_iov(ph->se, FUSE_NOTIFY_POLL, iov, 2); 2180 } else { 2181 return 0; 2182 } 2183} 2184 2185int fuse_lowlevel_notify_inval_inode(struct fuse_session *se, fuse_ino_t ino, 2186 off_t off, off_t len) 2187{ 2188 struct fuse_notify_inval_inode_out outarg = { 2189 .ino = ino, 2190 .off = off, 2191 .len = len, 2192 }; 2193 struct iovec iov[2]; 2194 2195 if (!se) { 2196 return -EINVAL; 2197 } 2198 2199 iov[1].iov_base = &outarg; 2200 iov[1].iov_len = sizeof(outarg); 2201 2202 return send_notify_iov(se, FUSE_NOTIFY_INVAL_INODE, iov, 2); 2203} 2204 2205int fuse_lowlevel_notify_inval_entry(struct fuse_session *se, fuse_ino_t parent, 2206 const char *name, size_t namelen) 2207{ 2208 struct fuse_notify_inval_entry_out outarg = { 2209 .parent = parent, 2210 .namelen = namelen, 2211 }; 2212 struct iovec iov[3]; 2213 2214 if (!se) { 2215 return -EINVAL; 2216 } 2217 2218 iov[1].iov_base = &outarg; 2219 iov[1].iov_len = sizeof(outarg); 2220 iov[2].iov_base = (void *)name; 2221 iov[2].iov_len = namelen + 1; 2222 2223 return send_notify_iov(se, FUSE_NOTIFY_INVAL_ENTRY, iov, 3); 2224} 2225 2226int fuse_lowlevel_notify_delete(struct fuse_session *se, fuse_ino_t parent, 2227 fuse_ino_t child, const char *name, 2228 size_t namelen) 2229{ 2230 struct fuse_notify_delete_out outarg = { 2231 .parent = parent, 2232 .child = child, 2233 .namelen = namelen, 2234 }; 2235 struct iovec iov[3]; 2236 2237 if (!se) { 2238 return -EINVAL; 2239 } 2240 2241 iov[1].iov_base = &outarg; 2242 iov[1].iov_len = sizeof(outarg); 2243 iov[2].iov_base = (void *)name; 2244 iov[2].iov_len = namelen + 1; 2245 2246 return send_notify_iov(se, FUSE_NOTIFY_DELETE, iov, 3); 2247} 2248 2249int fuse_lowlevel_notify_store(struct fuse_session *se, fuse_ino_t ino, 2250 off_t offset, struct fuse_bufvec *bufv) 2251{ 2252 struct fuse_out_header out = { 2253 .error = FUSE_NOTIFY_STORE, 2254 }; 2255 struct fuse_notify_store_out outarg = { 2256 .nodeid = ino, 2257 .offset = offset, 2258 .size = fuse_buf_size(bufv), 2259 }; 2260 struct iovec iov[3]; 2261 int res; 2262 2263 if (!se) { 2264 return -EINVAL; 2265 } 2266 2267 iov[0].iov_base = &out; 2268 iov[0].iov_len = sizeof(out); 2269 iov[1].iov_base = &outarg; 2270 iov[1].iov_len = sizeof(outarg); 2271 2272 res = fuse_send_data_iov(se, NULL, iov, 2, bufv); 2273 if (res > 0) { 2274 res = -res; 2275 } 2276 2277 return res; 2278} 2279 2280void *fuse_req_userdata(fuse_req_t req) 2281{ 2282 return req->se->userdata; 2283} 2284 2285const struct fuse_ctx *fuse_req_ctx(fuse_req_t req) 2286{ 2287 return &req->ctx; 2288} 2289 2290void fuse_req_interrupt_func(fuse_req_t req, fuse_interrupt_func_t func, 2291 void *data) 2292{ 2293 pthread_mutex_lock(&req->lock); 2294 pthread_mutex_lock(&req->se->lock); 2295 req->u.ni.func = func; 2296 req->u.ni.data = data; 2297 pthread_mutex_unlock(&req->se->lock); 2298 if (req->interrupted && func) { 2299 func(req, data); 2300 } 2301 pthread_mutex_unlock(&req->lock); 2302} 2303 2304int fuse_req_interrupted(fuse_req_t req) 2305{ 2306 int interrupted; 2307 2308 pthread_mutex_lock(&req->se->lock); 2309 interrupted = req->interrupted; 2310 pthread_mutex_unlock(&req->se->lock); 2311 2312 return interrupted; 2313} 2314 2315static struct { 2316 void (*func)(fuse_req_t, fuse_ino_t, struct fuse_mbuf_iter *); 2317 const char *name; 2318} fuse_ll_ops[] = { 2319 [FUSE_LOOKUP] = { do_lookup, "LOOKUP" }, 2320 [FUSE_FORGET] = { do_forget, "FORGET" }, 2321 [FUSE_GETATTR] = { do_getattr, "GETATTR" }, 2322 [FUSE_SETATTR] = { do_setattr, "SETATTR" }, 2323 [FUSE_READLINK] = { do_readlink, "READLINK" }, 2324 [FUSE_SYMLINK] = { do_symlink, "SYMLINK" }, 2325 [FUSE_MKNOD] = { do_mknod, "MKNOD" }, 2326 [FUSE_MKDIR] = { do_mkdir, "MKDIR" }, 2327 [FUSE_UNLINK] = { do_unlink, "UNLINK" }, 2328 [FUSE_RMDIR] = { do_rmdir, "RMDIR" }, 2329 [FUSE_RENAME] = { do_rename, "RENAME" }, 2330 [FUSE_LINK] = { do_link, "LINK" }, 2331 [FUSE_OPEN] = { do_open, "OPEN" }, 2332 [FUSE_READ] = { do_read, "READ" }, 2333 [FUSE_WRITE] = { do_write, "WRITE" }, 2334 [FUSE_STATFS] = { do_statfs, "STATFS" }, 2335 [FUSE_RELEASE] = { do_release, "RELEASE" }, 2336 [FUSE_FSYNC] = { do_fsync, "FSYNC" }, 2337 [FUSE_SETXATTR] = { do_setxattr, "SETXATTR" }, 2338 [FUSE_GETXATTR] = { do_getxattr, "GETXATTR" }, 2339 [FUSE_LISTXATTR] = { do_listxattr, "LISTXATTR" }, 2340 [FUSE_REMOVEXATTR] = { do_removexattr, "REMOVEXATTR" }, 2341 [FUSE_FLUSH] = { do_flush, "FLUSH" }, 2342 [FUSE_INIT] = { do_init, "INIT" }, 2343 [FUSE_OPENDIR] = { do_opendir, "OPENDIR" }, 2344 [FUSE_READDIR] = { do_readdir, "READDIR" }, 2345 [FUSE_RELEASEDIR] = { do_releasedir, "RELEASEDIR" }, 2346 [FUSE_FSYNCDIR] = { do_fsyncdir, "FSYNCDIR" }, 2347 [FUSE_GETLK] = { do_getlk, "GETLK" }, 2348 [FUSE_SETLK] = { do_setlk, "SETLK" }, 2349 [FUSE_SETLKW] = { do_setlkw, "SETLKW" }, 2350 [FUSE_ACCESS] = { do_access, "ACCESS" }, 2351 [FUSE_CREATE] = { do_create, "CREATE" }, 2352 [FUSE_INTERRUPT] = { do_interrupt, "INTERRUPT" }, 2353 [FUSE_BMAP] = { do_bmap, "BMAP" }, 2354 [FUSE_IOCTL] = { do_ioctl, "IOCTL" }, 2355 [FUSE_POLL] = { do_poll, "POLL" }, 2356 [FUSE_FALLOCATE] = { do_fallocate, "FALLOCATE" }, 2357 [FUSE_DESTROY] = { do_destroy, "DESTROY" }, 2358 [FUSE_NOTIFY_REPLY] = { NULL, "NOTIFY_REPLY" }, 2359 [FUSE_BATCH_FORGET] = { do_batch_forget, "BATCH_FORGET" }, 2360 [FUSE_READDIRPLUS] = { do_readdirplus, "READDIRPLUS" }, 2361 [FUSE_RENAME2] = { do_rename2, "RENAME2" }, 2362 [FUSE_COPY_FILE_RANGE] = { do_copy_file_range, "COPY_FILE_RANGE" }, 2363 [FUSE_LSEEK] = { do_lseek, "LSEEK" }, 2364}; 2365 2366#define FUSE_MAXOP (sizeof(fuse_ll_ops) / sizeof(fuse_ll_ops[0])) 2367 2368static const char *opname(enum fuse_opcode opcode) 2369{ 2370 if (opcode >= FUSE_MAXOP || !fuse_ll_ops[opcode].name) { 2371 return "???"; 2372 } else { 2373 return fuse_ll_ops[opcode].name; 2374 } 2375} 2376 2377void fuse_session_process_buf(struct fuse_session *se, 2378 const struct fuse_buf *buf) 2379{ 2380 struct fuse_bufvec bufv = { .buf[0] = *buf, .count = 1 }; 2381 fuse_session_process_buf_int(se, &bufv, NULL); 2382} 2383 2384/* 2385 * Restriction: 2386 * bufv is normally a single entry buffer, except for a write 2387 * where (if it's in memory) then the bufv may be multiple entries, 2388 * where the first entry contains all headers and subsequent entries 2389 * contain data 2390 * bufv shall not use any offsets etc to make the data anything 2391 * other than contiguous starting from 0. 2392 */ 2393void fuse_session_process_buf_int(struct fuse_session *se, 2394 struct fuse_bufvec *bufv, 2395 struct fuse_chan *ch) 2396{ 2397 const struct fuse_buf *buf = bufv->buf; 2398 struct fuse_mbuf_iter iter = FUSE_MBUF_ITER_INIT(buf); 2399 struct fuse_in_header *in; 2400 struct fuse_req *req; 2401 int err; 2402 2403 /* The first buffer must be a memory buffer */ 2404 assert(!(buf->flags & FUSE_BUF_IS_FD)); 2405 2406 in = fuse_mbuf_iter_advance(&iter, sizeof(*in)); 2407 assert(in); /* caller guarantees the input buffer is large enough */ 2408 2409 fuse_log( 2410 FUSE_LOG_DEBUG, 2411 "unique: %llu, opcode: %s (%i), nodeid: %llu, insize: %zu, pid: %u\n", 2412 (unsigned long long)in->unique, opname((enum fuse_opcode)in->opcode), 2413 in->opcode, (unsigned long long)in->nodeid, buf->size, in->pid); 2414 2415 req = fuse_ll_alloc_req(se); 2416 if (req == NULL) { 2417 struct fuse_out_header out = { 2418 .unique = in->unique, 2419 .error = -ENOMEM, 2420 }; 2421 struct iovec iov = { 2422 .iov_base = &out, 2423 .iov_len = sizeof(struct fuse_out_header), 2424 }; 2425 2426 fuse_send_msg(se, ch, &iov, 1); 2427 return; 2428 } 2429 2430 req->unique = in->unique; 2431 req->ctx.uid = in->uid; 2432 req->ctx.gid = in->gid; 2433 req->ctx.pid = in->pid; 2434 req->ch = ch; 2435 2436 /* 2437 * INIT and DESTROY requests are serialized, all other request types 2438 * run in parallel. This prevents races between FUSE_INIT and ordinary 2439 * requests, FUSE_INIT and FUSE_INIT, FUSE_INIT and FUSE_DESTROY, and 2440 * FUSE_DESTROY and FUSE_DESTROY. 2441 */ 2442 if (in->opcode == FUSE_INIT || in->opcode == CUSE_INIT || 2443 in->opcode == FUSE_DESTROY) { 2444 pthread_rwlock_wrlock(&se->init_rwlock); 2445 } else { 2446 pthread_rwlock_rdlock(&se->init_rwlock); 2447 } 2448 2449 err = EIO; 2450 if (!se->got_init) { 2451 enum fuse_opcode expected; 2452 2453 expected = se->cuse_data ? CUSE_INIT : FUSE_INIT; 2454 if (in->opcode != expected) { 2455 goto reply_err; 2456 } 2457 } else if (in->opcode == FUSE_INIT || in->opcode == CUSE_INIT) { 2458 if (fuse_lowlevel_is_virtio(se)) { 2459 /* 2460 * TODO: This is after a hard reboot typically, we need to do 2461 * a destroy, but we can't reply to this request yet so 2462 * we can't use do_destroy 2463 */ 2464 fuse_log(FUSE_LOG_DEBUG, "%s: reinit\n", __func__); 2465 se->got_destroy = 1; 2466 se->got_init = 0; 2467 if (se->op.destroy) { 2468 se->op.destroy(se->userdata); 2469 } 2470 } else { 2471 goto reply_err; 2472 } 2473 } 2474 2475 err = EACCES; 2476 /* Implement -o allow_root */ 2477 if (se->deny_others && in->uid != se->owner && in->uid != 0 && 2478 in->opcode != FUSE_INIT && in->opcode != FUSE_READ && 2479 in->opcode != FUSE_WRITE && in->opcode != FUSE_FSYNC && 2480 in->opcode != FUSE_RELEASE && in->opcode != FUSE_READDIR && 2481 in->opcode != FUSE_FSYNCDIR && in->opcode != FUSE_RELEASEDIR && 2482 in->opcode != FUSE_NOTIFY_REPLY && in->opcode != FUSE_READDIRPLUS) { 2483 goto reply_err; 2484 } 2485 2486 err = ENOSYS; 2487 if (in->opcode >= FUSE_MAXOP || !fuse_ll_ops[in->opcode].func) { 2488 goto reply_err; 2489 } 2490 if (in->opcode != FUSE_INTERRUPT) { 2491 struct fuse_req *intr; 2492 pthread_mutex_lock(&se->lock); 2493 intr = check_interrupt(se, req); 2494 list_add_req(req, &se->list); 2495 pthread_mutex_unlock(&se->lock); 2496 if (intr) { 2497 fuse_reply_err(intr, EAGAIN); 2498 } 2499 } 2500 2501 if (in->opcode == FUSE_WRITE && se->op.write_buf) { 2502 do_write_buf(req, in->nodeid, &iter, bufv); 2503 } else { 2504 fuse_ll_ops[in->opcode].func(req, in->nodeid, &iter); 2505 } 2506 2507 pthread_rwlock_unlock(&se->init_rwlock); 2508 return; 2509 2510reply_err: 2511 fuse_reply_err(req, err); 2512 pthread_rwlock_unlock(&se->init_rwlock); 2513} 2514 2515#define LL_OPTION(n, o, v) \ 2516 { \ 2517 n, offsetof(struct fuse_session, o), v \ 2518 } 2519 2520static const struct fuse_opt fuse_ll_opts[] = { 2521 LL_OPTION("debug", debug, 1), 2522 LL_OPTION("-d", debug, 1), 2523 LL_OPTION("--debug", debug, 1), 2524 LL_OPTION("allow_root", deny_others, 1), 2525 LL_OPTION("--socket-path=%s", vu_socket_path, 0), 2526 LL_OPTION("--fd=%d", vu_listen_fd, 0), 2527 LL_OPTION("--thread-pool-size=%d", thread_pool_size, 0), 2528 FUSE_OPT_END 2529}; 2530 2531void fuse_lowlevel_version(void) 2532{ 2533 printf("using FUSE kernel interface version %i.%i\n", FUSE_KERNEL_VERSION, 2534 FUSE_KERNEL_MINOR_VERSION); 2535} 2536 2537void fuse_lowlevel_help(void) 2538{ 2539 /* 2540 * These are not all options, but the ones that are 2541 * potentially of interest to an end-user 2542 */ 2543 printf( 2544 " -o allow_root allow access by root\n" 2545 " --socket-path=PATH path for the vhost-user socket\n" 2546 " --fd=FDNUM fd number of vhost-user socket\n" 2547 " --thread-pool-size=NUM thread pool size limit (default %d)\n", 2548 THREAD_POOL_SIZE); 2549} 2550 2551void fuse_session_destroy(struct fuse_session *se) 2552{ 2553 if (se->got_init && !se->got_destroy) { 2554 if (se->op.destroy) { 2555 se->op.destroy(se->userdata); 2556 } 2557 } 2558 pthread_rwlock_destroy(&se->init_rwlock); 2559 pthread_mutex_destroy(&se->lock); 2560 free(se->cuse_data); 2561 if (se->fd != -1) { 2562 close(se->fd); 2563 } 2564 2565 if (fuse_lowlevel_is_virtio(se)) { 2566 virtio_session_close(se); 2567 } 2568 2569 free(se->vu_socket_path); 2570 se->vu_socket_path = NULL; 2571 2572 free(se); 2573} 2574 2575 2576struct fuse_session *fuse_session_new(struct fuse_args *args, 2577 const struct fuse_lowlevel_ops *op, 2578 size_t op_size, void *userdata) 2579{ 2580 struct fuse_session *se; 2581 2582 if (sizeof(struct fuse_lowlevel_ops) < op_size) { 2583 fuse_log( 2584 FUSE_LOG_ERR, 2585 "fuse: warning: library too old, some operations may not work\n"); 2586 op_size = sizeof(struct fuse_lowlevel_ops); 2587 } 2588 2589 if (args->argc == 0) { 2590 fuse_log(FUSE_LOG_ERR, 2591 "fuse: empty argv passed to fuse_session_new().\n"); 2592 return NULL; 2593 } 2594 2595 se = (struct fuse_session *)calloc(1, sizeof(struct fuse_session)); 2596 if (se == NULL) { 2597 fuse_log(FUSE_LOG_ERR, "fuse: failed to allocate fuse object\n"); 2598 goto out1; 2599 } 2600 se->fd = -1; 2601 se->vu_listen_fd = -1; 2602 se->thread_pool_size = THREAD_POOL_SIZE; 2603 se->conn.max_write = UINT_MAX; 2604 se->conn.max_readahead = UINT_MAX; 2605 2606 /* Parse options */ 2607 if (fuse_opt_parse(args, se, fuse_ll_opts, NULL) == -1) { 2608 goto out2; 2609 } 2610 if (args->argc == 1 && args->argv[0][0] == '-') { 2611 fuse_log(FUSE_LOG_ERR, 2612 "fuse: warning: argv[0] looks like an option, but " 2613 "will be ignored\n"); 2614 } else if (args->argc != 1) { 2615 int i; 2616 fuse_log(FUSE_LOG_ERR, "fuse: unknown option(s): `"); 2617 for (i = 1; i < args->argc - 1; i++) { 2618 fuse_log(FUSE_LOG_ERR, "%s ", args->argv[i]); 2619 } 2620 fuse_log(FUSE_LOG_ERR, "%s'\n", args->argv[i]); 2621 goto out4; 2622 } 2623 2624 if (!se->vu_socket_path && se->vu_listen_fd < 0) { 2625 fuse_log(FUSE_LOG_ERR, "fuse: missing --socket-path or --fd option\n"); 2626 goto out4; 2627 } 2628 if (se->vu_socket_path && se->vu_listen_fd >= 0) { 2629 fuse_log(FUSE_LOG_ERR, 2630 "fuse: --socket-path and --fd cannot be given together\n"); 2631 goto out4; 2632 } 2633 2634 se->bufsize = FUSE_MAX_MAX_PAGES * getpagesize() + FUSE_BUFFER_HEADER_SIZE; 2635 2636 list_init_req(&se->list); 2637 list_init_req(&se->interrupts); 2638 fuse_mutex_init(&se->lock); 2639 pthread_rwlock_init(&se->init_rwlock, NULL); 2640 2641 memcpy(&se->op, op, op_size); 2642 se->owner = getuid(); 2643 se->userdata = userdata; 2644 2645 return se; 2646 2647out4: 2648 fuse_opt_free_args(args); 2649out2: 2650 free(se); 2651out1: 2652 return NULL; 2653} 2654 2655int fuse_session_mount(struct fuse_session *se) 2656{ 2657 return virtio_session_mount(se); 2658} 2659 2660int fuse_session_fd(struct fuse_session *se) 2661{ 2662 return se->fd; 2663} 2664 2665void fuse_session_unmount(struct fuse_session *se) 2666{ 2667} 2668 2669int fuse_lowlevel_is_virtio(struct fuse_session *se) 2670{ 2671 return !!se->virtio_dev; 2672} 2673 2674void fuse_session_exit(struct fuse_session *se) 2675{ 2676 se->exited = 1; 2677} 2678 2679void fuse_session_reset(struct fuse_session *se) 2680{ 2681 se->exited = 0; 2682 se->error = 0; 2683} 2684 2685int fuse_session_exited(struct fuse_session *se) 2686{ 2687 return se->exited; 2688}