diff options
author | Miklos Szeredi <mszeredi@suse.cz> | 2007-10-18 06:07:02 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@woody.linux-foundation.org> | 2007-10-18 17:37:31 -0400 |
commit | 6ff958edbf39c014eb06b65ad25b736be08c4e63 (patch) | |
tree | f87af1ae11b321cfa38c25378229f25942797385 | |
parent | 17637cbaba592076c221dc045ca78422b4af6290 (diff) |
fuse: add atomic open+truncate support
This patch allows fuse filesystems to implement open(..., O_TRUNC) as a single
request, instead of separate truncate and open requests.
Signed-off-by: Miklos Szeredi <mszeredi@suse.cz>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
-rw-r--r-- | fs/fuse/dir.c | 3 | ||||
-rw-r--r-- | fs/fuse/file.c | 4 | ||||
-rw-r--r-- | fs/fuse/fuse_i.h | 3 | ||||
-rw-r--r-- | fs/fuse/inode.c | 5 | ||||
-rw-r--r-- | include/linux/fuse.h | 1 |
5 files changed, 14 insertions, 2 deletions
diff --git a/fs/fuse/dir.c b/fs/fuse/dir.c index 537d38bee13c..052327bd6c9d 100644 --- a/fs/fuse/dir.c +++ b/fs/fuse/dir.c | |||
@@ -1083,6 +1083,9 @@ static int fuse_do_setattr(struct dentry *entry, struct iattr *attr, | |||
1083 | return err; | 1083 | return err; |
1084 | } | 1084 | } |
1085 | 1085 | ||
1086 | if ((attr->ia_valid & ATTR_OPEN) && fc->atomic_o_trunc) | ||
1087 | return 0; | ||
1088 | |||
1086 | if (attr->ia_valid & ATTR_SIZE) { | 1089 | if (attr->ia_valid & ATTR_SIZE) { |
1087 | unsigned long limit; | 1090 | unsigned long limit; |
1088 | if (IS_SWAPFILE(inode)) | 1091 | if (IS_SWAPFILE(inode)) |
diff --git a/fs/fuse/file.c b/fs/fuse/file.c index 4a28c3d37732..6726378661da 100644 --- a/fs/fuse/file.c +++ b/fs/fuse/file.c | |||
@@ -28,7 +28,9 @@ static int fuse_send_open(struct inode *inode, struct file *file, int isdir, | |||
28 | return PTR_ERR(req); | 28 | return PTR_ERR(req); |
29 | 29 | ||
30 | memset(&inarg, 0, sizeof(inarg)); | 30 | memset(&inarg, 0, sizeof(inarg)); |
31 | inarg.flags = file->f_flags & ~(O_CREAT | O_EXCL | O_NOCTTY | O_TRUNC); | 31 | inarg.flags = file->f_flags & ~(O_CREAT | O_EXCL | O_NOCTTY); |
32 | if (!fc->atomic_o_trunc) | ||
33 | inarg.flags &= ~O_TRUNC; | ||
32 | req->in.h.opcode = isdir ? FUSE_OPENDIR : FUSE_OPEN; | 34 | req->in.h.opcode = isdir ? FUSE_OPENDIR : FUSE_OPEN; |
33 | req->in.h.nodeid = get_node_id(inode); | 35 | req->in.h.nodeid = get_node_id(inode); |
34 | req->in.numargs = 1; | 36 | req->in.numargs = 1; |
diff --git a/fs/fuse/fuse_i.h b/fs/fuse/fuse_i.h index ffbcadaa7d67..b24fc9b386f8 100644 --- a/fs/fuse/fuse_i.h +++ b/fs/fuse/fuse_i.h | |||
@@ -320,6 +320,9 @@ struct fuse_conn { | |||
320 | /** Do readpages asynchronously? Only set in INIT */ | 320 | /** Do readpages asynchronously? Only set in INIT */ |
321 | unsigned async_read : 1; | 321 | unsigned async_read : 1; |
322 | 322 | ||
323 | /** Do not send separate SETATTR request before open(O_TRUNC) */ | ||
324 | unsigned atomic_o_trunc : 1; | ||
325 | |||
323 | /* | 326 | /* |
324 | * The following bitfields are only for optimization purposes | 327 | * The following bitfields are only for optimization purposes |
325 | * and hence races in setting them will not cause malfunction | 328 | * and hence races in setting them will not cause malfunction |
diff --git a/fs/fuse/inode.c b/fs/fuse/inode.c index 6ef3973f4048..3c13981f48e2 100644 --- a/fs/fuse/inode.c +++ b/fs/fuse/inode.c | |||
@@ -531,6 +531,8 @@ static void process_init_reply(struct fuse_conn *fc, struct fuse_req *req) | |||
531 | fc->async_read = 1; | 531 | fc->async_read = 1; |
532 | if (!(arg->flags & FUSE_POSIX_LOCKS)) | 532 | if (!(arg->flags & FUSE_POSIX_LOCKS)) |
533 | fc->no_lock = 1; | 533 | fc->no_lock = 1; |
534 | if (arg->flags & FUSE_ATOMIC_O_TRUNC) | ||
535 | fc->atomic_o_trunc = 1; | ||
534 | } else { | 536 | } else { |
535 | ra_pages = fc->max_read / PAGE_CACHE_SIZE; | 537 | ra_pages = fc->max_read / PAGE_CACHE_SIZE; |
536 | fc->no_lock = 1; | 538 | fc->no_lock = 1; |
@@ -553,7 +555,8 @@ static void fuse_send_init(struct fuse_conn *fc, struct fuse_req *req) | |||
553 | arg->major = FUSE_KERNEL_VERSION; | 555 | arg->major = FUSE_KERNEL_VERSION; |
554 | arg->minor = FUSE_KERNEL_MINOR_VERSION; | 556 | arg->minor = FUSE_KERNEL_MINOR_VERSION; |
555 | arg->max_readahead = fc->bdi.ra_pages * PAGE_CACHE_SIZE; | 557 | arg->max_readahead = fc->bdi.ra_pages * PAGE_CACHE_SIZE; |
556 | arg->flags |= FUSE_ASYNC_READ | FUSE_POSIX_LOCKS | FUSE_FILE_OPS; | 558 | arg->flags |= FUSE_ASYNC_READ | FUSE_POSIX_LOCKS | FUSE_FILE_OPS | |
559 | FUSE_ATOMIC_O_TRUNC; | ||
557 | req->in.h.opcode = FUSE_INIT; | 560 | req->in.h.opcode = FUSE_INIT; |
558 | req->in.numargs = 1; | 561 | req->in.numargs = 1; |
559 | req->in.args[0].size = sizeof(*arg); | 562 | req->in.args[0].size = sizeof(*arg); |
diff --git a/include/linux/fuse.h b/include/linux/fuse.h index 43a77d73349c..436047093bc4 100644 --- a/include/linux/fuse.h +++ b/include/linux/fuse.h | |||
@@ -101,6 +101,7 @@ struct fuse_file_lock { | |||
101 | #define FUSE_ASYNC_READ (1 << 0) | 101 | #define FUSE_ASYNC_READ (1 << 0) |
102 | #define FUSE_POSIX_LOCKS (1 << 1) | 102 | #define FUSE_POSIX_LOCKS (1 << 1) |
103 | #define FUSE_FILE_OPS (1 << 2) | 103 | #define FUSE_FILE_OPS (1 << 2) |
104 | #define FUSE_ATOMIC_O_TRUNC (1 << 3) | ||
104 | 105 | ||
105 | /** | 106 | /** |
106 | * Release flags | 107 | * Release flags |