* [PATCH] fuse: add support for SEEK_HOLE and SEEK_DATA in lseek
@ 2016-01-15 5:27 Ravishankar N
2016-01-15 5:34 ` Ravishankar N
0 siblings, 1 reply; 2+ messages in thread
From: Ravishankar N @ 2016-01-15 5:27 UTC (permalink / raw)
To: torvalds, david, viro
Cc: linux-kernel, linux-fsdevel, fuse-devel, Ravishankar N,
Miklos Szeredi
A useful performance improvement for accessing virtual machine images
via FUSE mount.
See https://bugzilla.redhat.com/show_bug.cgi?id=1220173 for a use-case
for glusterFS.
Signed-off-by: Ravishankar N <ravishankar@redhat.com>
Signed-off-by: Miklos Szeredi <miklos@szeredi.hu>
---
fs/fuse/file.c | 73 +++++++++++++++++++++++++++++++++++++++++------
fs/fuse/fuse_i.h | 3 ++
include/uapi/linux/fuse.h | 17 ++++++++++-
3 files changed, 84 insertions(+), 9 deletions(-)
diff --git a/fs/fuse/file.c b/fs/fuse/file.c
index 570ca40..aa03aab 100644
--- a/fs/fuse/file.c
+++ b/fs/fuse/file.c
@@ -2231,20 +2231,77 @@ static sector_t fuse_bmap(struct address_space *mapping, sector_t block)
return err ? 0 : outarg.block;
}
+static loff_t fuse_lseek(struct file *file, loff_t offset, int whence)
+{
+ struct inode *inode = file->f_mapping->host;
+ struct fuse_conn *fc = get_fuse_conn(inode);
+ struct fuse_file *ff = file->private_data;
+ FUSE_ARGS(args);
+ struct fuse_lseek_in inarg = {
+ .fh = ff->fh,
+ .offset = offset,
+ .whence = whence
+ };
+ struct fuse_lseek_out outarg;
+ int err;
+
+ if (fc->no_lseek)
+ goto fallback;
+
+ args.in.h.opcode = FUSE_LSEEK;
+ args.in.h.nodeid = ff->nodeid;
+ args.in.numargs = 1;
+ args.in.args[0].size = sizeof(inarg);
+ args.in.args[0].value = &inarg;
+ args.out.numargs = 1;
+ args.out.args[0].size = sizeof(outarg);
+ args.out.args[0].value = &outarg;
+ err = fuse_simple_request(fc, &args);
+ if (err) {
+ if (err == -ENOSYS) {
+ fc->no_lseek = 1;
+ goto fallback;
+ }
+ return err;
+ }
+
+ return vfs_setpos(file, outarg.offset, inode->i_sb->s_maxbytes);
+
+fallback:
+ err = fuse_update_attributes(inode, NULL, file, NULL);
+ if (!err)
+ return generic_file_llseek(file, offset, whence);
+ else
+ return err;
+}
+
static loff_t fuse_file_llseek(struct file *file, loff_t offset, int whence)
{
loff_t retval;
struct inode *inode = file_inode(file);
- /* No i_mutex protection necessary for SEEK_CUR and SEEK_SET */
- if (whence == SEEK_CUR || whence == SEEK_SET)
- return generic_file_llseek(file, offset, whence);
-
- mutex_lock(&inode->i_mutex);
- retval = fuse_update_attributes(inode, NULL, file, NULL);
- if (!retval)
+ switch (whence) {
+ case SEEK_SET:
+ case SEEK_CUR:
+ /* No i_mutex protection necessary for SEEK_CUR and SEEK_SET */
retval = generic_file_llseek(file, offset, whence);
- mutex_unlock(&inode->i_mutex);
+ break;
+ case SEEK_END:
+ mutex_lock(&inode->i_mutex);
+ retval = fuse_update_attributes(inode, NULL, file, NULL);
+ if (!retval)
+ retval = generic_file_llseek(file, offset, whence);
+ mutex_unlock(&inode->i_mutex);
+ break;
+ case SEEK_HOLE:
+ case SEEK_DATA:
+ mutex_lock(&inode->i_mutex);
+ retval = fuse_lseek(file, offset, whence);
+ mutex_unlock(&inode->i_mutex);
+ break;
+ default:
+ retval = -EINVAL;
+ }
return retval;
}
diff --git a/fs/fuse/fuse_i.h b/fs/fuse/fuse_i.h
index 4051131..ce394b5 100644
--- a/fs/fuse/fuse_i.h
+++ b/fs/fuse/fuse_i.h
@@ -605,6 +605,9 @@ struct fuse_conn {
/** Does the filesystem support asynchronous direct-IO submission? */
unsigned async_dio:1;
+ /** Is lseek not implemented by fs? */
+ unsigned no_lseek:1;
+
/** The number of requests waiting for completion */
atomic_t num_waiting;
diff --git a/include/uapi/linux/fuse.h b/include/uapi/linux/fuse.h
index c9aca04..5974fae 100644
--- a/include/uapi/linux/fuse.h
+++ b/include/uapi/linux/fuse.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,
@@ -758,4 +762,15 @@ struct fuse_notify_retrieve_in {
/* Device ioctls: */
#define FUSE_DEV_IOC_CLONE _IOR(229, 0, uint32_t)
+struct fuse_lseek_in {
+ uint64_t fh;
+ uint64_t offset;
+ uint32_t whence;
+ uint32_t padding;
+};
+
+struct fuse_lseek_out {
+ uint64_t offset;
+};
+
#endif /* _LINUX_FUSE_H */
--
2.5.0
^ permalink raw reply related [flat|nested] 2+ messages in thread
* Re: [PATCH] fuse: add support for SEEK_HOLE and SEEK_DATA in lseek
2016-01-15 5:27 [PATCH] fuse: add support for SEEK_HOLE and SEEK_DATA in lseek Ravishankar N
@ 2016-01-15 5:34 ` Ravishankar N
0 siblings, 0 replies; 2+ messages in thread
From: Ravishankar N @ 2016-01-15 5:34 UTC (permalink / raw)
To: torvalds, david, viro
Cc: linux-kernel, linux-fsdevel, fuse-devel, Miklos Szeredi
On 01/15/2016 10:57 AM, Ravishankar N wrote:
> A useful performance improvement for accessing virtual machine images
> via FUSE mount.
>
> See https://bugzilla.redhat.com/show_bug.cgi?id=1220173 for a use-case
> for glusterFS.
Hello Linus/ fs maintainers,
Please consider taking this patch in for the next mainline release.
I had sent it on fuse-devel and subsequently Miklos had queued an updated
version [1] for linux-next which I tested to be working. Since then,
Nikolaus
Rath has taken over the maintainerhsip of libfuse but not fs/fuse. Since
I am not receiving any replies [2] from Miklos for this patch, I am
doing what
Nikolaus suggested: send it out to other maintainers to see if someone can
merge it.
FWIW, the patch itself is rather straight forward and has been signed
off by
Miklos so there shouldn't be any problem in taking it in.
Thanks,
Ravi
[1]http://sourceforge.net/p/fuse/mailman/message/34610775/
[2] https://lkml.org/lkml/2015/12/17/80
> Signed-off-by: Ravishankar N <ravishankar@redhat.com>
> Signed-off-by: Miklos Szeredi <miklos@szeredi.hu>
> ---
> fs/fuse/file.c | 73 +++++++++++++++++++++++++++++++++++++++++------
> fs/fuse/fuse_i.h | 3 ++
> include/uapi/linux/fuse.h | 17 ++++++++++-
> 3 files changed, 84 insertions(+), 9 deletions(-)
>
> diff --git a/fs/fuse/file.c b/fs/fuse/file.c
> index 570ca40..aa03aab 100644
> --- a/fs/fuse/file.c
> +++ b/fs/fuse/file.c
> @@ -2231,20 +2231,77 @@ static sector_t fuse_bmap(struct address_space *mapping, sector_t block)
> return err ? 0 : outarg.block;
> }
>
> +static loff_t fuse_lseek(struct file *file, loff_t offset, int whence)
> +{
> + struct inode *inode = file->f_mapping->host;
> + struct fuse_conn *fc = get_fuse_conn(inode);
> + struct fuse_file *ff = file->private_data;
> + FUSE_ARGS(args);
> + struct fuse_lseek_in inarg = {
> + .fh = ff->fh,
> + .offset = offset,
> + .whence = whence
> + };
> + struct fuse_lseek_out outarg;
> + int err;
> +
> + if (fc->no_lseek)
> + goto fallback;
> +
> + args.in.h.opcode = FUSE_LSEEK;
> + args.in.h.nodeid = ff->nodeid;
> + args.in.numargs = 1;
> + args.in.args[0].size = sizeof(inarg);
> + args.in.args[0].value = &inarg;
> + args.out.numargs = 1;
> + args.out.args[0].size = sizeof(outarg);
> + args.out.args[0].value = &outarg;
> + err = fuse_simple_request(fc, &args);
> + if (err) {
> + if (err == -ENOSYS) {
> + fc->no_lseek = 1;
> + goto fallback;
> + }
> + return err;
> + }
> +
> + return vfs_setpos(file, outarg.offset, inode->i_sb->s_maxbytes);
> +
> +fallback:
> + err = fuse_update_attributes(inode, NULL, file, NULL);
> + if (!err)
> + return generic_file_llseek(file, offset, whence);
> + else
> + return err;
> +}
> +
> static loff_t fuse_file_llseek(struct file *file, loff_t offset, int whence)
> {
> loff_t retval;
> struct inode *inode = file_inode(file);
>
> - /* No i_mutex protection necessary for SEEK_CUR and SEEK_SET */
> - if (whence == SEEK_CUR || whence == SEEK_SET)
> - return generic_file_llseek(file, offset, whence);
> -
> - mutex_lock(&inode->i_mutex);
> - retval = fuse_update_attributes(inode, NULL, file, NULL);
> - if (!retval)
> + switch (whence) {
> + case SEEK_SET:
> + case SEEK_CUR:
> + /* No i_mutex protection necessary for SEEK_CUR and SEEK_SET */
> retval = generic_file_llseek(file, offset, whence);
> - mutex_unlock(&inode->i_mutex);
> + break;
> + case SEEK_END:
> + mutex_lock(&inode->i_mutex);
> + retval = fuse_update_attributes(inode, NULL, file, NULL);
> + if (!retval)
> + retval = generic_file_llseek(file, offset, whence);
> + mutex_unlock(&inode->i_mutex);
> + break;
> + case SEEK_HOLE:
> + case SEEK_DATA:
> + mutex_lock(&inode->i_mutex);
> + retval = fuse_lseek(file, offset, whence);
> + mutex_unlock(&inode->i_mutex);
> + break;
> + default:
> + retval = -EINVAL;
> + }
>
> return retval;
> }
> diff --git a/fs/fuse/fuse_i.h b/fs/fuse/fuse_i.h
> index 4051131..ce394b5 100644
> --- a/fs/fuse/fuse_i.h
> +++ b/fs/fuse/fuse_i.h
> @@ -605,6 +605,9 @@ struct fuse_conn {
> /** Does the filesystem support asynchronous direct-IO submission? */
> unsigned async_dio:1;
>
> + /** Is lseek not implemented by fs? */
> + unsigned no_lseek:1;
> +
> /** The number of requests waiting for completion */
> atomic_t num_waiting;
>
> diff --git a/include/uapi/linux/fuse.h b/include/uapi/linux/fuse.h
> index c9aca04..5974fae 100644
> --- a/include/uapi/linux/fuse.h
> +++ b/include/uapi/linux/fuse.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,
> @@ -758,4 +762,15 @@ struct fuse_notify_retrieve_in {
> /* Device ioctls: */
> #define FUSE_DEV_IOC_CLONE _IOR(229, 0, uint32_t)
>
> +struct fuse_lseek_in {
> + uint64_t fh;
> + uint64_t offset;
> + uint32_t whence;
> + uint32_t padding;
> +};
> +
> +struct fuse_lseek_out {
> + uint64_t offset;
> +};
> +
> #endif /* _LINUX_FUSE_H */
^ permalink raw reply [flat|nested] 2+ messages in thread
end of thread, other threads:[~2016-01-15 5:34 UTC | newest]
Thread overview: 2+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2016-01-15 5:27 [PATCH] fuse: add support for SEEK_HOLE and SEEK_DATA in lseek Ravishankar N
2016-01-15 5:34 ` Ravishankar N
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).