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 {  | 
