summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--contrib/fuse-include/fuse_kernel.h17
-rw-r--r--xlators/mount/fuse/src/fuse-bridge.c64
-rw-r--r--xlators/mount/fuse/src/fuse-bridge.h4
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 {