summaryrefslogtreecommitdiffstats
path: root/xlators/mount
diff options
context:
space:
mode:
Diffstat (limited to 'xlators/mount')
-rw-r--r--xlators/mount/fuse/src/fuse-bridge.c64
-rw-r--r--xlators/mount/fuse/src/fuse-bridge.h4
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 {