Skip to content

Commit

Permalink
fuse: add FALLOCATE operation
Browse files Browse the repository at this point in the history
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.

Signed-off-by: Anatol Pomozov <anatol.pomozov@gmail.com>
Signed-off-by: Miklos Szeredi <mszeredi@suse.cz>
  • Loading branch information
Anatol Pomozov authored and Miklos Szeredi committed Apr 25, 2012
1 parent e269069 commit 05ba1f0
Show file tree
Hide file tree
Showing 2 changed files with 46 additions and 1 deletion.
33 changes: 33 additions & 0 deletions fs/fuse/file.c
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand All @@ -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 = {
Expand All @@ -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 */
};

Expand Down
14 changes: 13 additions & 1 deletion include/linux/fuse.h
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,9 @@
* 7.18
* - add FUSE_IOCTL_DIR flag
* - add FUSE_NOTIFY_DELETE
*
* 7.19
* - add FUSE_FALLOCATE
*/

#ifndef _LINUX_FUSE_H
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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,
Expand Down Expand Up @@ -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;
Expand Down

0 comments on commit 05ba1f0

Please sign in to comment.