virtiofsd pull 2021-05-06

A pile of cleanups:
 
   Use of glib allocators from Mahmoud
   Virtio spec compliance and printf cleanup from me.
   Sugar to turn on xattr when defining xattr mapping from Carlos
   an assert cleanup from Greg
 
 Signed-off-by: Dr. David Alan Gilbert <dgilbert@redhat.com>
 -----BEGIN PGP SIGNATURE-----
 
 iQIzBAABCAAdFiEERfXHG0oMt/uXep+pBRYzHrxb/ecFAmCUO1oACgkQBRYzHrxb
 /eelvhAAmQmeEB1z7CiY70o4i8qzj3rFVeT+DK1jxAJARMyvQSbQsACGvFS/SCx7
 mXmmkKBZ0GnPXReRJt0aa6ChIQpJPVccCD2olnBD7W9BaRmltNYfScC0qS9Qp7nv
 GEkxYnWtRwNRwMG3j0QxegLIoW5YmM3eaTuJKbnRcW3OBjB9eFN86qrb1Bc5v+1g
 Q7WVRfjYWzUwH8RpfN5fVpRHF228ngTnh3CBSPpqiIAcoLv9reKmWG+JdeUpUskA
 dH/ezsrJggI5AOYAabEuP4VESS0+ZBL5xQ33sr2t/EN+EK43vLZL/LhBppyyWT1y
 1LtLYU7ODNQF/sbuZfItITrMWL+qGUCvPnL74GiJDBovGmYtd9oxC9VAoT2gsZqK
 7oQ6B2gikpBG9RKFNsRFzbyFLtiSsIQ0Qee7qlOzg3rKKoAXIkHdUxYH7COjCE3N
 osG/fL1Z5FFxS4OS4zgMwSCgm/ss4MixhtBc8+zzklMhUmMDGaj6mw+l2LZmEj/r
 LgvFit6IEassFnCOL4tseNE+5WuljaTuGZpFJbW+Oll79RBYEsHZnoiSrclrIDsG
 +NWdaix4OKL8X508sqaA7hEz2e4LHOkw1HtOhlchRkfyvmZOydC4/EU+49qV88Iz
 +jBt66aBC6OVs43FG4Kn1QxB58eUzXb9oeNuvdpVv9rZ1wt8OCI=
 =Aw0R
 -----END PGP SIGNATURE-----

Merge remote-tracking branch 'remotes/dgilbert-gitlab/tags/pull-virtiofs-20210506' into staging

virtiofsd pull 2021-05-06

A pile of cleanups:

  Use of glib allocators from Mahmoud
  Virtio spec compliance and printf cleanup from me.
  Sugar to turn on xattr when defining xattr mapping from Carlos
  an assert cleanup from Greg

Signed-off-by: Dr. David Alan Gilbert <dgilbert@redhat.com>

# gpg: Signature made Thu 06 May 2021 19:54:18 BST
# gpg:                using RSA key 45F5C71B4A0CB7FB977A9FA90516331EBC5BFDE7
# gpg: Good signature from "Dr. David Alan Gilbert (RH2) <dgilbert@redhat.com>" [full]
# Primary key fingerprint: 45F5 C71B 4A0C B7FB 977A  9FA9 0516 331E BC5B FDE7

* remotes/dgilbert-gitlab/tags/pull-virtiofs-20210506:
  virtiofsd/fuse_virtio.c: Changed allocations of locals to GLib
  virtiofsd/passthrough_ll.c: Changed local allocations to GLib functions
  virtiofsd: Changed allocations of fv_VuDev & its internals to GLib functions
  virtiofsd: Changed allocation of lo_map_elems to GLib's functions
  virtiofsd: Changed allocations of fuse_session to GLib's functions
  virtiofsd: Changed allocations of iovec to GLib's functions
  virtiofsd: Changed allocations of fuse_req to GLib functions
  virtiofsd: Don't assume header layout
  virtiofs: Fixup printf args
  virtiofsd: Add help for -o xattr-mapping
  virtiofsd: Allow use "-o xattrmap" without "-o xattr"
  virtiofsd: Fix side-effect in assert()

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
master
Peter Maydell 2021-05-11 13:03:44 +01:00
commit f9a576a818
4 changed files with 139 additions and 100 deletions

View File

@ -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;
}

View File

@ -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;
}

View File

@ -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"

View File

@ -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);
}