diff options
Diffstat (limited to 'xlators/mount')
-rw-r--r-- | xlators/mount/fuse/src/fuse-bridge.c | 64 | ||||
-rw-r--r-- | xlators/mount/fuse/src/fuse-bridge.h | 4 |
2 files changed, 67 insertions, 1 deletions
diff --git a/xlators/mount/fuse/src/fuse-bridge.c b/xlators/mount/fuse/src/fuse-bridge.c index 724a70b8149..ff42ec11273 100644 --- a/xlators/mount/fuse/src/fuse-bridge.c +++ b/xlators/mount/fuse/src/fuse-bridge.c @@ -2393,6 +2393,66 @@ fuse_write (xlator_t *this, fuse_in_header_t *finh, void *msg) return; } +#if FUSE_KERNEL_MINOR_VERSION >= 24 && HAVE_SEEK_HOLE +static int +fuse_lseek_cbk (call_frame_t *frame, void *cookie, xlator_t *this, + int32_t op_ret, int32_t op_errno, off_t offset, dict_t *xdata) +{ + fuse_state_t *state = frame->root->state; + fuse_in_header_t *finh = state->finh; + struct fuse_lseek_out flo = {0, }; + + fuse_log_eh_fop (this, state, frame, op_ret, op_errno); + + if (op_ret >= 0) { + flo.offset = offset; + send_fuse_obj (this, finh, &flo); + } else { + send_fuse_err (this, finh, op_errno); + } + + free_fuse_state (state); + STACK_DESTROY (frame->root); + + return 0; +} + +static void +fuse_lseek_resume (fuse_state_t *state) +{ + FUSE_FOP (state, fuse_lseek_cbk, GF_FOP_SEEK, seek, state->fd, + state->off, state->whence, state->xdata); +} + +static void +fuse_lseek (xlator_t *this, fuse_in_header_t *finh, void *msg) +{ + struct fuse_lseek_in *ffi = msg; + fuse_state_t *state = NULL; + + GET_STATE (this, finh, state); + state->fd = FH_TO_FD (ffi->fh); + state->off = ffi->offset; + + switch (ffi->whence) { + case SEEK_DATA: + state->whence = GF_SEEK_DATA; + break; + case SEEK_HOLE: + state->whence = GF_SEEK_HOLE; + break; + default: + /* fuse should handle other whence internally */ + send_fuse_err (this, finh, EINVAL); + free_fuse_state (state); + return; + } + + fuse_resolve_fd_init (state, &state->resolve, state->fd); + fuse_resolve_and_resume (state, fuse_lseek_resume); +} +#endif /* FUSE_KERNEL_MINOR_VERSION >= 24 && HAVE_SEEK_HOLE */ + void fuse_flush_resume (fuse_state_t *state) { @@ -5327,6 +5387,10 @@ static fuse_handler_t *fuse_std_ops[FUSE_OP_HIGH] = { #if FUSE_KERNEL_MINOR_VERSION >= 21 [FUSE_READDIRPLUS] = fuse_readdirp, #endif + +#if FUSE_KERNEL_MINOR_VERSION >= 24 && HAVE_SEEK_HOLE + [FUSE_LSEEK] = fuse_lseek, +#endif }; diff --git a/xlators/mount/fuse/src/fuse-bridge.h b/xlators/mount/fuse/src/fuse-bridge.h index d337ea08539..1da04c57f8f 100644 --- a/xlators/mount/fuse/src/fuse-bridge.h +++ b/xlators/mount/fuse/src/fuse-bridge.h @@ -41,7 +41,7 @@ #include "gidcache.h" #if defined(GF_LINUX_HOST_OS) || defined(__FreeBSD__) || defined(__NetBSD__) -#define FUSE_OP_HIGH (FUSE_READDIRPLUS + 1) +#define FUSE_OP_HIGH (FUSE_LSEEK + 1) #endif #ifdef GF_DARWIN_HOST_OS #define FUSE_OP_HIGH (FUSE_DESTROY + 1) @@ -380,6 +380,8 @@ typedef struct { uuid_t gfid; uint32_t io_flags; int32_t fd_no; + + gf_seek_what_t whence; } fuse_state_t; typedef struct { |