From: Miklos S. <mi...@sz...> - 2012-04-24 14:11:16
|
Anatol Pomozov <ana...@gm...> writes: > fallocate filesystem operation preallocates media space for the given file. > If fallocate returns success then any subsequent write to the given range > never fails with 'not enough space' error. Patch looks good, applied. Thanks, Miklos > > Signed-off-by: Anatol Pomozov <ana...@gm...> > --- > fs/fuse/file.c | 33 +++++++++++++++++++++++++++++++++ > include/linux/fuse.h | 14 +++++++++++++- > 2 files changed, 46 insertions(+), 1 deletion(-) > > diff --git a/fs/fuse/file.c b/fs/fuse/file.c > index 504e61b..e3fee88 100644 > --- a/fs/fuse/file.c > +++ b/fs/fuse/file.c > @@ -2171,6 +2171,37 @@ fuse_direct_IO(int rw, struct kiocb *iocb, const struct iovec *iov, > return ret; > } > > +long fuse_file_fallocate(struct file *file, int mode, loff_t offset, > + loff_t length) > +{ > + struct fuse_file *ff = file->private_data; > + struct fuse_conn *fc = ff->fc; > + struct fuse_req *req; > + struct fuse_fallocate_in inarg = { > + .fh = ff->fh, > + .offset = offset, > + .length = length, > + .mode = mode > + }; > + int err; > + > + req = fuse_get_req(fc); > + if (IS_ERR(req)) > + return PTR_ERR(req); > + > + req->in.h.opcode = FUSE_FALLOCATE; > + req->in.h.nodeid = ff->nodeid; > + req->in.numargs = 1; > + req->in.args[0].size = sizeof(inarg); > + req->in.args[0].value = &inarg; > + fuse_request_send(fc, req); > + err = req->out.h.error; > + fuse_put_request(fc, req); > + > + return err; > +} > +EXPORT_SYMBOL_GPL(fuse_file_fallocate); > + > static const struct file_operations fuse_file_operations = { > .llseek = fuse_file_llseek, > .read = do_sync_read, > @@ -2188,6 +2219,7 @@ static const struct file_operations fuse_file_operations = { > .unlocked_ioctl = fuse_file_ioctl, > .compat_ioctl = fuse_file_compat_ioctl, > .poll = fuse_file_poll, > + .fallocate = fuse_file_fallocate, > }; > > static const struct file_operations fuse_direct_io_file_operations = { > @@ -2204,6 +2236,7 @@ static const struct file_operations fuse_direct_io_file_operations = { > .unlocked_ioctl = fuse_file_ioctl, > .compat_ioctl = fuse_file_compat_ioctl, > .poll = fuse_file_poll, > + .fallocate = fuse_file_fallocate, > /* no splice_read */ > }; > > diff --git a/include/linux/fuse.h b/include/linux/fuse.h > index 8f2ab8f..9303348 100644 > --- a/include/linux/fuse.h > +++ b/include/linux/fuse.h > @@ -54,6 +54,9 @@ > * 7.18 > * - add FUSE_IOCTL_DIR flag > * - add FUSE_NOTIFY_DELETE > + * > + * 7.19 > + * - add FUSE_FALLOCATE > */ > > #ifndef _LINUX_FUSE_H > @@ -85,7 +88,7 @@ > #define FUSE_KERNEL_VERSION 7 > > /** Minor version number of this interface */ > -#define FUSE_KERNEL_MINOR_VERSION 18 > +#define FUSE_KERNEL_MINOR_VERSION 19 > > /** The node ID of the root inode */ > #define FUSE_ROOT_ID 1 > @@ -278,6 +281,7 @@ enum fuse_opcode { > FUSE_POLL = 40, > FUSE_NOTIFY_REPLY = 41, > FUSE_BATCH_FORGET = 42, > + FUSE_FALLOCATE = 43, > > /* CUSE specific operations */ > CUSE_INIT = 4096, > @@ -571,6 +575,14 @@ struct fuse_notify_poll_wakeup_out { > __u64 kh; > }; > > +struct fuse_fallocate_in { > + __u64 fh; > + __u64 offset; > + __u64 length; > + __u32 mode; > + __u32 padding; > +}; > + > struct fuse_in_header { > __u32 len; > __u32 opcode; |