summaryrefslogtreecommitdiffstats
path: root/xlators/mount
diff options
context:
space:
mode:
authorNiels de Vos <ndevos@redhat.com>2015-07-06 00:01:44 +0200
committerRaghavendra G <rgowdapp@redhat.com>2016-02-10 22:16:50 -0800
commite501a7da4c50e2a2049a71119c25ed43b43f3395 (patch)
tree24bd91edea724e1820f8b4a8cb65801a2629b551 /xlators/mount
parentb8bd9a6e6e3f50ede4c25dcfc0a05aad53e66c79 (diff)
fuse: add support for SEEK_HOLE and SEEK_DATA through lseek()
The Linux FUSE kernel module has gained support for passing SEEK_HOLE and SEEK_DATA on through lseek(). This can greatly improve performance when working with sparse files. Linux FUSE introduced support for lseek() with version 4.5. The commit in mainline Linux is 0b5da8db145bfd44266ac964a2636a0cf8d7c286. URL: http://thread.gmane.org/gmane.comp.file-systems.fuse.devel/14752 Change-Id: I12496d788e59461a3023ddd30e0ea3179007f77e BUG: 1220173 Signed-off-by: Ravishankar N <ravishankar@redhat.com> Signed-off-by: Niels de Vos <ndevos@redhat.com> Reviewed-on: http://review.gluster.org/11474 Smoke: Gluster Build System <jenkins@build.gluster.com> CentOS-regression: Gluster Build System <jenkins@build.gluster.com> NetBSD-regression: NetBSD Build System <jenkins@build.gluster.org> Reviewed-by: Raghavendra G <rgowdapp@redhat.com>
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 {