diff options
-rw-r--r-- | contrib/fuse-include/fuse_kernel.h | 17 | ||||
-rw-r--r-- | xlators/mount/fuse/src/fuse-bridge.c | 64 | ||||
-rw-r--r-- | xlators/mount/fuse/src/fuse-bridge.h | 4 |
3 files changed, 83 insertions, 2 deletions
diff --git a/contrib/fuse-include/fuse_kernel.h b/contrib/fuse-include/fuse_kernel.h index 25084a052a1..1e41e237e6f 100644 --- a/contrib/fuse-include/fuse_kernel.h +++ b/contrib/fuse-include/fuse_kernel.h @@ -102,6 +102,9 @@ * - add ctime and ctimensec to fuse_setattr_in * - add FUSE_RENAME2 request * - add FUSE_NO_OPEN_SUPPORT flag + * + * 7.24 + * - add FUSE_LSEEK for SEEK_HOLE and SEEK_DATA support */ #ifndef _LINUX_FUSE_H @@ -137,7 +140,7 @@ #define FUSE_KERNEL_VERSION 7 /** Minor version number of this interface */ -#define FUSE_KERNEL_MINOR_VERSION 23 +#define FUSE_KERNEL_MINOR_VERSION 24 /** The node ID of the root inode */ #define FUSE_ROOT_ID 1 @@ -358,6 +361,7 @@ enum fuse_opcode { FUSE_FALLOCATE = 43, FUSE_READDIRPLUS = 44, FUSE_RENAME2 = 45, + FUSE_LSEEK = 46, /* CUSE specific operations */ CUSE_INIT = 4096, @@ -755,4 +759,15 @@ struct fuse_notify_retrieve_in { uint64_t dummy4; }; +struct fuse_lseek_in { + uint64_t fh; + uint64_t offset; + int32_t whence; + uint32_t padding; +}; + +struct fuse_lseek_out { + uint64_t offset; +}; + #endif /* _LINUX_FUSE_H */ 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 { |