diff options
-rw-r--r-- | tools/virtiofsd/fuse_lowlevel.c | 43 | ||||
-rw-r--r-- | tools/virtiofsd/fuse_virtio.c | 129 | ||||
-rw-r--r-- | tools/virtiofsd/helper.c | 3 | ||||
-rw-r--r-- | tools/virtiofsd/passthrough_ll.c | 64 |
4 files changed, 139 insertions, 100 deletions
diff --git a/tools/virtiofsd/fuse_lowlevel.c b/tools/virtiofsd/fuse_lowlevel.c index 58e32fc963..7fe2cef1eb 100644 --- a/tools/virtiofsd/fuse_lowlevel.c +++ b/tools/virtiofsd/fuse_lowlevel.c @@ -106,7 +106,7 @@ static void list_add_req(struct fuse_req *req, struct fuse_req *next) static void destroy_req(fuse_req_t req) { pthread_mutex_destroy(&req->lock); - free(req); + g_free(req); } void fuse_free_req(fuse_req_t req) @@ -130,7 +130,7 @@ static struct fuse_req *fuse_ll_alloc_req(struct fuse_session *se) { struct fuse_req *req; - req = (struct fuse_req *)calloc(1, sizeof(struct fuse_req)); + req = g_try_new0(struct fuse_req, 1); if (req == NULL) { fuse_log(FUSE_LOG_ERR, "fuse: failed to allocate request\n"); } else { @@ -217,9 +217,9 @@ static int send_reply(fuse_req_t req, int error, const void *arg, int fuse_reply_iov(fuse_req_t req, const struct iovec *iov, int count) { int res; - struct iovec *padded_iov; + g_autofree struct iovec *padded_iov = NULL; - padded_iov = malloc((count + 1) * sizeof(struct iovec)); + padded_iov = g_try_new(struct iovec, count + 1); if (padded_iov == NULL) { return fuse_reply_err(req, ENOMEM); } @@ -228,7 +228,6 @@ int fuse_reply_iov(fuse_req_t req, const struct iovec *iov, int count) count++; res = send_reply_iov(req, 0, padded_iov, count); - free(padded_iov); return res; } @@ -568,7 +567,7 @@ static struct fuse_ioctl_iovec *fuse_ioctl_iovec_copy(const struct iovec *iov, struct fuse_ioctl_iovec *fiov; size_t i; - fiov = malloc(sizeof(fiov[0]) * count); + fiov = g_try_new(struct fuse_ioctl_iovec, count); if (!fiov) { return NULL; } @@ -586,8 +585,8 @@ int fuse_reply_ioctl_retry(fuse_req_t req, const struct iovec *in_iov, size_t out_count) { struct fuse_ioctl_out arg; - struct fuse_ioctl_iovec *in_fiov = NULL; - struct fuse_ioctl_iovec *out_fiov = NULL; + g_autofree struct fuse_ioctl_iovec *in_fiov = NULL; + g_autofree struct fuse_ioctl_iovec *out_fiov = NULL; struct iovec iov[4]; size_t count = 1; int res; @@ -603,13 +602,14 @@ int fuse_reply_ioctl_retry(fuse_req_t req, const struct iovec *in_iov, /* Can't handle non-compat 64bit ioctls on 32bit */ if (sizeof(void *) == 4 && req->ioctl_64bit) { res = fuse_reply_err(req, EINVAL); - goto out; + return res; } if (in_count) { in_fiov = fuse_ioctl_iovec_copy(in_iov, in_count); if (!in_fiov) { - goto enomem; + res = fuse_reply_err(req, ENOMEM); + return res; } iov[count].iov_base = (void *)in_fiov; @@ -619,7 +619,8 @@ int fuse_reply_ioctl_retry(fuse_req_t req, const struct iovec *in_iov, if (out_count) { out_fiov = fuse_ioctl_iovec_copy(out_iov, out_count); if (!out_fiov) { - goto enomem; + res = fuse_reply_err(req, ENOMEM); + return res; } iov[count].iov_base = (void *)out_fiov; @@ -628,15 +629,8 @@ int fuse_reply_ioctl_retry(fuse_req_t req, const struct iovec *in_iov, } res = send_reply_iov(req, 0, iov, count); -out: - free(in_fiov); - free(out_fiov); return res; - -enomem: - res = fuse_reply_err(req, ENOMEM); - goto out; } int fuse_reply_ioctl(fuse_req_t req, int result, const void *buf, size_t size) @@ -663,11 +657,11 @@ int fuse_reply_ioctl(fuse_req_t req, int result, const void *buf, size_t size) int fuse_reply_ioctl_iov(fuse_req_t req, int result, const struct iovec *iov, int count) { - struct iovec *padded_iov; + g_autofree struct iovec *padded_iov = NULL; struct fuse_ioctl_out arg; int res; - padded_iov = malloc((count + 2) * sizeof(struct iovec)); + padded_iov = g_try_new(struct iovec, count + 2); if (padded_iov == NULL) { return fuse_reply_err(req, ENOMEM); } @@ -680,7 +674,6 @@ int fuse_reply_ioctl_iov(fuse_req_t req, int result, const struct iovec *iov, memcpy(&padded_iov[2], iov, count * sizeof(struct iovec)); res = send_reply_iov(req, 0, padded_iov, count + 2); - free(padded_iov); return res; } @@ -1684,7 +1677,7 @@ static struct fuse_req *check_interrupt(struct fuse_session *se, if (curr->u.i.unique == req->unique) { req->interrupted = 1; list_del_req(curr); - free(curr); + g_free(curr); return NULL; } } @@ -2477,7 +2470,7 @@ void fuse_session_destroy(struct fuse_session *se) free(se->vu_socket_path); se->vu_socket_path = NULL; - free(se); + g_free(se); } @@ -2500,7 +2493,7 @@ struct fuse_session *fuse_session_new(struct fuse_args *args, return NULL; } - se = (struct fuse_session *)calloc(1, sizeof(struct fuse_session)); + se = g_try_new0(struct fuse_session, 1); if (se == NULL) { fuse_log(FUSE_LOG_ERR, "fuse: failed to allocate fuse object\n"); goto out1; @@ -2560,7 +2553,7 @@ struct fuse_session *fuse_session_new(struct fuse_args *args, out4: fuse_opt_free_args(args); out2: - free(se); + g_free(se); out1: return NULL; } diff --git a/tools/virtiofsd/fuse_virtio.c b/tools/virtiofsd/fuse_virtio.c index 3e13997406..1170f375a5 100644 --- a/tools/virtiofsd/fuse_virtio.c +++ b/tools/virtiofsd/fuse_virtio.c @@ -129,18 +129,55 @@ static void fv_panic(VuDev *dev, const char *err) * Copy from an iovec into a fuse_buf (memory only) * Caller must ensure there is space */ -static void copy_from_iov(struct fuse_buf *buf, size_t out_num, - const struct iovec *out_sg) +static size_t copy_from_iov(struct fuse_buf *buf, size_t out_num, + const struct iovec *out_sg, + size_t max) { void *dest = buf->mem; + size_t copied = 0; - while (out_num) { + while (out_num && max) { size_t onelen = out_sg->iov_len; + onelen = MIN(onelen, max); memcpy(dest, out_sg->iov_base, onelen); dest += onelen; + copied += onelen; out_sg++; out_num--; + max -= onelen; } + + return copied; +} + +/* + * Skip 'skip' bytes in the iov; 'sg_1stindex' is set as + * the index for the 1st iovec to read data from, and + * 'sg_1stskip' is the number of bytes to skip in that entry. + * + * Returns True if there are at least 'skip' bytes in the iovec + * + */ +static bool skip_iov(const struct iovec *sg, size_t sg_size, + size_t skip, + size_t *sg_1stindex, size_t *sg_1stskip) +{ + size_t vec; + + for (vec = 0; vec < sg_size; vec++) { + if (sg[vec].iov_len > skip) { + *sg_1stskip = skip; + *sg_1stindex = vec; + + return true; + } + + skip -= sg[vec].iov_len; + } + + *sg_1stindex = vec; + *sg_1stskip = 0; + return skip == 0; } /* @@ -294,6 +331,7 @@ int virtio_send_data_iov(struct fuse_session *se, struct fuse_chan *ch, VuVirtq *q = vu_get_queue(dev, qi->qidx); VuVirtqElement *elem = &req->elem; int ret = 0; + g_autofree struct iovec *in_sg_cpy = NULL; assert(count >= 1); assert(iov[0].iov_len >= sizeof(struct fuse_out_header)); @@ -347,8 +385,7 @@ int virtio_send_data_iov(struct fuse_session *se, struct fuse_chan *ch, * Build a copy of the the in_sg iov so we can skip bits in it, * including changing the offsets */ - struct iovec *in_sg_cpy = calloc(sizeof(struct iovec), in_num); - assert(in_sg_cpy); + in_sg_cpy = g_new(struct iovec, in_num); memcpy(in_sg_cpy, in_sg, sizeof(struct iovec) * in_num); /* These get updated as we skip */ struct iovec *in_sg_ptr = in_sg_cpy; @@ -386,7 +423,6 @@ int virtio_send_data_iov(struct fuse_session *se, struct fuse_chan *ch, ret = errno; fuse_log(FUSE_LOG_DEBUG, "%s: preadv failed (%m) len=%zd\n", __func__, len); - free(in_sg_cpy); goto err; } fuse_log(FUSE_LOG_DEBUG, "%s: preadv ret=%d len=%zd\n", __func__, @@ -410,13 +446,11 @@ int virtio_send_data_iov(struct fuse_session *se, struct fuse_chan *ch, if (ret != len) { fuse_log(FUSE_LOG_DEBUG, "%s: ret!=len\n", __func__); ret = EIO; - free(in_sg_cpy); goto err; } in_sg_left -= ret; len -= ret; } while (in_sg_left); - free(in_sg_cpy); /* Need to fix out->len on EOF */ if (len) { @@ -457,6 +491,7 @@ static void fv_queue_worker(gpointer data, gpointer user_data) bool allocated_bufv = false; struct fuse_bufvec bufv; struct fuse_bufvec *pbufv; + struct fuse_in_header inh; assert(se->bufsize > sizeof(struct fuse_in_header)); @@ -476,8 +511,7 @@ static void fv_queue_worker(gpointer data, gpointer user_data) * They're spread over multiple descriptors in a scatter/gather set * and we can't trust the guest to keep them still; so copy in/out. */ - fbuf.mem = malloc(se->bufsize); - assert(fbuf.mem); + fbuf.mem = g_malloc(se->bufsize); fuse_mutex_init(&req->ch.lock); req->ch.fd = -1; @@ -505,14 +539,15 @@ static void fv_queue_worker(gpointer data, gpointer user_data) elem->index); assert(0); /* TODO */ } - /* Copy just the first element and look at it */ - copy_from_iov(&fbuf, 1, out_sg); + /* Copy just the fuse_in_header and look at it */ + copy_from_iov(&fbuf, out_num, out_sg, + sizeof(struct fuse_in_header)); + memcpy(&inh, fbuf.mem, sizeof(struct fuse_in_header)); pbufv = NULL; /* Compiler thinks an unitialised path */ - if (out_num > 2 && - out_sg[0].iov_len == sizeof(struct fuse_in_header) && - ((struct fuse_in_header *)fbuf.mem)->opcode == FUSE_WRITE && - out_sg[1].iov_len == sizeof(struct fuse_write_in)) { + if (inh.opcode == FUSE_WRITE && + out_len >= (sizeof(struct fuse_in_header) + + sizeof(struct fuse_write_in))) { /* * For a write we don't actually need to copy the * data, we can just do it straight out of guest memory @@ -521,15 +556,15 @@ static void fv_queue_worker(gpointer data, gpointer user_data) */ fuse_log(FUSE_LOG_DEBUG, "%s: Write special case\n", __func__); - /* copy the fuse_write_in header afte rthe fuse_in_header */ - fbuf.mem += out_sg->iov_len; - copy_from_iov(&fbuf, 1, out_sg + 1); - fbuf.mem -= out_sg->iov_len; - fbuf.size = out_sg[0].iov_len + out_sg[1].iov_len; + fbuf.size = copy_from_iov(&fbuf, out_num, out_sg, + sizeof(struct fuse_in_header) + + sizeof(struct fuse_write_in)); + /* That copy reread the in_header, make sure we use the original */ + memcpy(fbuf.mem, &inh, sizeof(struct fuse_in_header)); /* Allocate the bufv, with space for the rest of the iov */ - pbufv = malloc(sizeof(struct fuse_bufvec) + - sizeof(struct fuse_buf) * (out_num - 2)); + pbufv = g_try_malloc(sizeof(struct fuse_bufvec) + + sizeof(struct fuse_buf) * out_num); if (!pbufv) { fuse_log(FUSE_LOG_ERR, "%s: pbufv malloc failed\n", __func__); @@ -540,24 +575,37 @@ static void fv_queue_worker(gpointer data, gpointer user_data) pbufv->count = 1; pbufv->buf[0] = fbuf; - size_t iovindex, pbufvindex; - iovindex = 2; /* 2 headers, separate iovs */ + size_t iovindex, pbufvindex, iov_bytes_skip; pbufvindex = 1; /* 2 headers, 1 fusebuf */ + if (!skip_iov(out_sg, out_num, + sizeof(struct fuse_in_header) + + sizeof(struct fuse_write_in), + &iovindex, &iov_bytes_skip)) { + fuse_log(FUSE_LOG_ERR, "%s: skip failed\n", + __func__); + goto out; + } + for (; iovindex < out_num; iovindex++, pbufvindex++) { pbufv->count++; pbufv->buf[pbufvindex].pos = ~0; /* Dummy */ pbufv->buf[pbufvindex].flags = 0; pbufv->buf[pbufvindex].mem = out_sg[iovindex].iov_base; pbufv->buf[pbufvindex].size = out_sg[iovindex].iov_len; + + if (iov_bytes_skip) { + pbufv->buf[pbufvindex].mem += iov_bytes_skip; + pbufv->buf[pbufvindex].size -= iov_bytes_skip; + iov_bytes_skip = 0; + } } } else { /* Normal (non fast write) path */ - /* Copy the rest of the buffer */ - fbuf.mem += out_sg->iov_len; - copy_from_iov(&fbuf, out_num - 1, out_sg + 1); - fbuf.mem -= out_sg->iov_len; + copy_from_iov(&fbuf, out_num, out_sg, se->bufsize); + /* That copy reread the in_header, make sure we use the original */ + memcpy(fbuf.mem, &inh, sizeof(struct fuse_in_header)); fbuf.size = out_len; /* TODO! Endianness of header */ @@ -573,7 +621,7 @@ static void fv_queue_worker(gpointer data, gpointer user_data) out: if (allocated_bufv) { - free(pbufv); + g_free(pbufv); } /* If the request has no reply, still recycle the virtqueue element */ @@ -592,7 +640,7 @@ out: } pthread_mutex_destroy(&req->ch.lock); - free(fbuf.mem); + g_free(fbuf.mem); free(req); } @@ -733,7 +781,7 @@ static void fv_queue_cleanup_thread(struct fv_VuDev *vud, int qidx) pthread_mutex_destroy(&ourqi->vq_lock); close(ourqi->kill_fd); ourqi->kick_fd = -1; - free(vud->qi[qidx]); + g_free(vud->qi[qidx]); vud->qi[qidx] = NULL; } @@ -764,15 +812,13 @@ static void fv_queue_set_started(VuDev *dev, int qidx, bool started) if (started) { /* Fire up a thread to watch this queue */ if (qidx >= vud->nqueues) { - vud->qi = realloc(vud->qi, (qidx + 1) * sizeof(vud->qi[0])); - assert(vud->qi); + vud->qi = g_realloc_n(vud->qi, qidx + 1, sizeof(vud->qi[0])); memset(vud->qi + vud->nqueues, 0, sizeof(vud->qi[0]) * (1 + (qidx - vud->nqueues))); vud->nqueues = qidx + 1; } if (!vud->qi[qidx]) { - vud->qi[qidx] = calloc(sizeof(struct fv_QueueInfo), 1); - assert(vud->qi[qidx]); + vud->qi[qidx] = g_new0(struct fv_QueueInfo, 1); vud->qi[qidx]->virtio_dev = vud; vud->qi[qidx]->qidx = qidx; } else { @@ -1038,12 +1084,7 @@ int virtio_session_mount(struct fuse_session *se) __func__); /* TODO: Some cleanup/deallocation! */ - se->virtio_dev = calloc(sizeof(struct fv_VuDev), 1); - if (!se->virtio_dev) { - fuse_log(FUSE_LOG_ERR, "%s: virtio_dev calloc failed\n", __func__); - close(data_sock); - return -1; - } + se->virtio_dev = g_new0(struct fv_VuDev, 1); se->vu_socketfd = data_sock; se->virtio_dev->se = se; @@ -1065,8 +1106,8 @@ void virtio_session_close(struct fuse_session *se) return; } - free(se->virtio_dev->qi); + g_free(se->virtio_dev->qi); pthread_rwlock_destroy(&se->virtio_dev->vu_dispatch_rwlock); - free(se->virtio_dev); + g_free(se->virtio_dev); se->virtio_dev = NULL; } diff --git a/tools/virtiofsd/helper.c b/tools/virtiofsd/helper.c index 28243b51b2..5e98ed702b 100644 --- a/tools/virtiofsd/helper.c +++ b/tools/virtiofsd/helper.c @@ -172,6 +172,9 @@ void fuse_cmdline_help(void) " default: no_writeback\n" " -o xattr|no_xattr enable/disable xattr\n" " default: no_xattr\n" + " -o xattrmap=<mapping> Enable xattr mapping (enables xattr)\n" + " <mapping> is a string consists of a series of rules\n" + " e.g. -o xattrmap=:map::user.virtiofs.:\n" " -o modcaps=CAPLIST Modify the list of capabilities\n" " e.g. -o modcaps=+sys_admin:-chown\n" " --rlimit-nofile=<num> set maximum number of file descriptors\n" diff --git a/tools/virtiofsd/passthrough_ll.c b/tools/virtiofsd/passthrough_ll.c index 1553d2ef45..49c21fd855 100644 --- a/tools/virtiofsd/passthrough_ll.c +++ b/tools/virtiofsd/passthrough_ll.c @@ -406,7 +406,7 @@ static void lo_map_init(struct lo_map *map) static void lo_map_destroy(struct lo_map *map) { - free(map->elems); + g_free(map->elems); } static int lo_map_grow(struct lo_map *map, size_t new_nelems) @@ -418,7 +418,7 @@ static int lo_map_grow(struct lo_map *map, size_t new_nelems) return 1; } - new_elems = realloc(map->elems, sizeof(map->elems[0]) * new_nelems); + new_elems = g_try_realloc_n(map->elems, new_nelems, sizeof(map->elems[0])); if (!new_elems) { return 0; } @@ -1653,7 +1653,7 @@ static void lo_do_readdir(fuse_req_t req, fuse_ino_t ino, size_t size, struct lo_data *lo = lo_data(req); struct lo_dirp *d = NULL; struct lo_inode *dinode; - char *buf = NULL; + g_autofree char *buf = NULL; char *p; size_t rem = size; int err = EBADF; @@ -1669,7 +1669,7 @@ static void lo_do_readdir(fuse_req_t req, fuse_ino_t ino, size_t size, } err = ENOMEM; - buf = calloc(1, size); + buf = g_try_malloc0(size); if (!buf) { goto error; } @@ -1755,7 +1755,6 @@ error: } else { fuse_reply_buf(req, buf, size - rem); } - free(buf); } static void lo_readdir(fuse_req_t req, fuse_ino_t ino, size_t size, @@ -2011,10 +2010,10 @@ static void lo_getlk(fuse_req_t req, fuse_ino_t ino, struct fuse_file_info *fi, fuse_log(FUSE_LOG_DEBUG, "lo_getlk(ino=%" PRIu64 ", flags=%d)" - " owner=0x%lx, l_type=%d l_start=0x%lx" - " l_len=0x%lx\n", - ino, fi->flags, fi->lock_owner, lock->l_type, lock->l_start, - lock->l_len); + " owner=0x%" PRIx64 ", l_type=%d l_start=0x%" PRIx64 + " l_len=0x%" PRIx64 "\n", + ino, fi->flags, fi->lock_owner, lock->l_type, + (uint64_t)lock->l_start, (uint64_t)lock->l_len); if (!lo->posix_lock) { fuse_reply_err(req, ENOSYS); @@ -2061,10 +2060,10 @@ static void lo_setlk(fuse_req_t req, fuse_ino_t ino, struct fuse_file_info *fi, fuse_log(FUSE_LOG_DEBUG, "lo_setlk(ino=%" PRIu64 ", flags=%d)" - " cmd=%d pid=%d owner=0x%lx sleep=%d l_whence=%d" - " l_start=0x%lx l_len=0x%lx\n", + " cmd=%d pid=%d owner=0x%" PRIx64 " sleep=%d l_whence=%d" + " l_start=0x%" PRIx64 " l_len=0x%" PRIx64 "\n", ino, fi->flags, lock->l_type, lock->l_pid, fi->lock_owner, sleep, - lock->l_whence, lock->l_start, lock->l_len); + lock->l_whence, (uint64_t)lock->l_start, (uint64_t)lock->l_len); if (!lo->posix_lock) { fuse_reply_err(req, ENOSYS); @@ -2723,11 +2722,16 @@ static int xattr_map_server(const struct lo_data *lo, const char *server_name, return -ENODATA; } +#define FCHDIR_NOFAIL(fd) do { \ + int fchdir_res = fchdir(fd); \ + assert(fchdir_res == 0); \ + } while (0) + static void lo_getxattr(fuse_req_t req, fuse_ino_t ino, const char *in_name, size_t size) { struct lo_data *lo = lo_data(req); - char *value = NULL; + g_autofree char *value = NULL; char procname[64]; const char *name; char *mapped_name; @@ -2768,7 +2772,7 @@ static void lo_getxattr(fuse_req_t req, fuse_ino_t ino, const char *in_name, ino, name, size); if (size) { - value = malloc(size); + value = g_try_malloc(size); if (!value) { goto out_err; } @@ -2789,9 +2793,9 @@ static void lo_getxattr(fuse_req_t req, fuse_ino_t ino, const char *in_name, ret = fgetxattr(fd, name, value, size); } else { /* fchdir should not fail here */ - assert(fchdir(lo->proc_self_fd) == 0); + FCHDIR_NOFAIL(lo->proc_self_fd); ret = getxattr(procname, name, value, size); - assert(fchdir(lo->root.fd) == 0); + FCHDIR_NOFAIL(lo->root.fd); } if (ret == -1) { @@ -2807,8 +2811,6 @@ static void lo_getxattr(fuse_req_t req, fuse_ino_t ino, const char *in_name, fuse_reply_xattr(req, ret); } out_free: - free(value); - if (fd >= 0) { close(fd); } @@ -2827,7 +2829,7 @@ out: static void lo_listxattr(fuse_req_t req, fuse_ino_t ino, size_t size) { struct lo_data *lo = lo_data(req); - char *value = NULL; + g_autofree char *value = NULL; char procname[64]; struct lo_inode *inode; ssize_t ret; @@ -2849,7 +2851,7 @@ static void lo_listxattr(fuse_req_t req, fuse_ino_t ino, size_t size) size); if (size) { - value = malloc(size); + value = g_try_malloc(size); if (!value) { goto out_err; } @@ -2864,9 +2866,9 @@ static void lo_listxattr(fuse_req_t req, fuse_ino_t ino, size_t size) ret = flistxattr(fd, value, size); } else { /* fchdir should not fail here */ - assert(fchdir(lo->proc_self_fd) == 0); + FCHDIR_NOFAIL(lo->proc_self_fd); ret = listxattr(procname, value, size); - assert(fchdir(lo->root.fd) == 0); + FCHDIR_NOFAIL(lo->root.fd); } if (ret == -1) { @@ -2934,8 +2936,6 @@ static void lo_listxattr(fuse_req_t req, fuse_ino_t ino, size_t size) fuse_reply_xattr(req, ret); } out_free: - free(value); - if (fd >= 0) { close(fd); } @@ -3000,9 +3000,9 @@ static void lo_setxattr(fuse_req_t req, fuse_ino_t ino, const char *in_name, ret = fsetxattr(fd, name, value, size, flags); } else { /* fchdir should not fail here */ - assert(fchdir(lo->proc_self_fd) == 0); + FCHDIR_NOFAIL(lo->proc_self_fd); ret = setxattr(procname, name, value, size, flags); - assert(fchdir(lo->root.fd) == 0); + FCHDIR_NOFAIL(lo->root.fd); } saverr = ret == -1 ? errno : 0; @@ -3066,9 +3066,9 @@ static void lo_removexattr(fuse_req_t req, fuse_ino_t ino, const char *in_name) ret = fremovexattr(fd, name); } else { /* fchdir should not fail here */ - assert(fchdir(lo->proc_self_fd) == 0); + FCHDIR_NOFAIL(lo->proc_self_fd); ret = removexattr(procname, name); - assert(fchdir(lo->root.fd) == 0); + FCHDIR_NOFAIL(lo->root.fd); } saverr = ret == -1 ? errno : 0; @@ -3097,9 +3097,10 @@ static void lo_copy_file_range(fuse_req_t req, fuse_ino_t ino_in, off_t off_in, fuse_log(FUSE_LOG_DEBUG, "lo_copy_file_range(ino=%" PRIu64 "/fd=%d, " - "off=%lu, ino=%" PRIu64 "/fd=%d, " - "off=%lu, size=%zd, flags=0x%x)\n", - ino_in, in_fd, off_in, ino_out, out_fd, off_out, len, flags); + "off=%ju, ino=%" PRIu64 "/fd=%d, " + "off=%ju, size=%zd, flags=0x%x)\n", + ino_in, in_fd, (intmax_t)off_in, + ino_out, out_fd, (intmax_t)off_out, len, flags); res = copy_file_range(in_fd, &off_in, out_fd, &off_out, len, flags); if (res < 0) { @@ -3826,6 +3827,7 @@ int main(int argc, char *argv[]) } if (lo.xattrmap) { + lo.xattr = 1; parse_xattrmap(&lo); } |