aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMiklos Szeredi <mszeredi@suse.cz>2007-11-28 19:22:00 -0500
committerLinus Torvalds <torvalds@woody.linux-foundation.org>2007-11-29 12:24:54 -0500
commita6643094e73247c1ebd36816f494f631fa7be348 (patch)
tree11ba2e666b6fea1cdf579616d6a04b0afd24f61c
parent7dca9fd39f7d4605ac178a67bb1772381056917d (diff)
fuse: pass open flags to read and write
Some open flags (O_APPEND, O_DIRECT) can be changed with fcntl(F_SETFL, ...) after open, but fuse currently only sends the flags to userspace in open. To make it possible to correcly handle changing flags, send the current value to userspace in each read and write. 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.c3
-rw-r--r--fs/fuse/file.c26
-rw-r--r--fs/fuse/fuse_i.h2
-rw-r--r--include/linux/fuse.h5
4 files changed, 22 insertions, 14 deletions
diff --git a/fs/fuse/dir.c b/fs/fuse/dir.c
index c84f825b57e7..dfc32dc97f7f 100644
--- a/fs/fuse/dir.c
+++ b/fs/fuse/dir.c
@@ -964,7 +964,6 @@ static int fuse_readdir(struct file *file, void *dstbuf, filldir_t filldir)
964 struct page *page; 964 struct page *page;
965 struct inode *inode = file->f_path.dentry->d_inode; 965 struct inode *inode = file->f_path.dentry->d_inode;
966 struct fuse_conn *fc = get_fuse_conn(inode); 966 struct fuse_conn *fc = get_fuse_conn(inode);
967 struct fuse_file *ff = file->private_data;
968 struct fuse_req *req; 967 struct fuse_req *req;
969 968
970 if (is_bad_inode(inode)) 969 if (is_bad_inode(inode))
@@ -981,7 +980,7 @@ static int fuse_readdir(struct file *file, void *dstbuf, filldir_t filldir)
981 } 980 }
982 req->num_pages = 1; 981 req->num_pages = 1;
983 req->pages[0] = page; 982 req->pages[0] = page;
984 fuse_read_fill(req, ff, inode, file->f_pos, PAGE_SIZE, FUSE_READDIR); 983 fuse_read_fill(req, file, inode, file->f_pos, PAGE_SIZE, FUSE_READDIR);
985 request_send(fc, req); 984 request_send(fc, req);
986 nbytes = req->out.args[0].size; 985 nbytes = req->out.args[0].size;
987 err = req->out.h.error; 986 err = req->out.h.error;
diff --git a/fs/fuse/file.c b/fs/fuse/file.c
index 474968fbb555..bb05d227cf30 100644
--- a/fs/fuse/file.c
+++ b/fs/fuse/file.c
@@ -289,14 +289,16 @@ static int fuse_fsync(struct file *file, struct dentry *de, int datasync)
289 return fuse_fsync_common(file, de, datasync, 0); 289 return fuse_fsync_common(file, de, datasync, 0);
290} 290}
291 291
292void fuse_read_fill(struct fuse_req *req, struct fuse_file *ff, 292void fuse_read_fill(struct fuse_req *req, struct file *file,
293 struct inode *inode, loff_t pos, size_t count, int opcode) 293 struct inode *inode, loff_t pos, size_t count, int opcode)
294{ 294{
295 struct fuse_read_in *inarg = &req->misc.read_in; 295 struct fuse_read_in *inarg = &req->misc.read_in;
296 struct fuse_file *ff = file->private_data;
296 297
297 inarg->fh = ff->fh; 298 inarg->fh = ff->fh;
298 inarg->offset = pos; 299 inarg->offset = pos;
299 inarg->size = count; 300 inarg->size = count;
301 inarg->flags = file->f_flags;
300 req->in.h.opcode = opcode; 302 req->in.h.opcode = opcode;
301 req->in.h.nodeid = get_node_id(inode); 303 req->in.h.nodeid = get_node_id(inode);
302 req->in.numargs = 1; 304 req->in.numargs = 1;
@@ -313,9 +315,8 @@ static size_t fuse_send_read(struct fuse_req *req, struct file *file,
313 fl_owner_t owner) 315 fl_owner_t owner)
314{ 316{
315 struct fuse_conn *fc = get_fuse_conn(inode); 317 struct fuse_conn *fc = get_fuse_conn(inode);
316 struct fuse_file *ff = file->private_data;
317 318
318 fuse_read_fill(req, ff, inode, pos, count, FUSE_READ); 319 fuse_read_fill(req, file, inode, pos, count, FUSE_READ);
319 if (owner != NULL) { 320 if (owner != NULL) {
320 struct fuse_read_in *inarg = &req->misc.read_in; 321 struct fuse_read_in *inarg = &req->misc.read_in;
321 322
@@ -376,15 +377,16 @@ static void fuse_readpages_end(struct fuse_conn *fc, struct fuse_req *req)
376 fuse_put_request(fc, req); 377 fuse_put_request(fc, req);
377} 378}
378 379
379static void fuse_send_readpages(struct fuse_req *req, struct fuse_file *ff, 380static void fuse_send_readpages(struct fuse_req *req, struct file *file,
380 struct inode *inode) 381 struct inode *inode)
381{ 382{
382 struct fuse_conn *fc = get_fuse_conn(inode); 383 struct fuse_conn *fc = get_fuse_conn(inode);
383 loff_t pos = page_offset(req->pages[0]); 384 loff_t pos = page_offset(req->pages[0]);
384 size_t count = req->num_pages << PAGE_CACHE_SHIFT; 385 size_t count = req->num_pages << PAGE_CACHE_SHIFT;
385 req->out.page_zeroing = 1; 386 req->out.page_zeroing = 1;
386 fuse_read_fill(req, ff, inode, pos, count, FUSE_READ); 387 fuse_read_fill(req, file, inode, pos, count, FUSE_READ);
387 if (fc->async_read) { 388 if (fc->async_read) {
389 struct fuse_file *ff = file->private_data;
388 req->ff = fuse_file_get(ff); 390 req->ff = fuse_file_get(ff);
389 req->end = fuse_readpages_end; 391 req->end = fuse_readpages_end;
390 request_send_background(fc, req); 392 request_send_background(fc, req);
@@ -396,7 +398,7 @@ static void fuse_send_readpages(struct fuse_req *req, struct fuse_file *ff,
396 398
397struct fuse_fill_data { 399struct fuse_fill_data {
398 struct fuse_req *req; 400 struct fuse_req *req;
399 struct fuse_file *ff; 401 struct file *file;
400 struct inode *inode; 402 struct inode *inode;
401}; 403};
402 404
@@ -411,7 +413,7 @@ static int fuse_readpages_fill(void *_data, struct page *page)
411 (req->num_pages == FUSE_MAX_PAGES_PER_REQ || 413 (req->num_pages == FUSE_MAX_PAGES_PER_REQ ||
412 (req->num_pages + 1) * PAGE_CACHE_SIZE > fc->max_read || 414 (req->num_pages + 1) * PAGE_CACHE_SIZE > fc->max_read ||
413 req->pages[req->num_pages - 1]->index + 1 != page->index)) { 415 req->pages[req->num_pages - 1]->index + 1 != page->index)) {
414 fuse_send_readpages(req, data->ff, inode); 416 fuse_send_readpages(req, data->file, inode);
415 data->req = req = fuse_get_req(fc); 417 data->req = req = fuse_get_req(fc);
416 if (IS_ERR(req)) { 418 if (IS_ERR(req)) {
417 unlock_page(page); 419 unlock_page(page);
@@ -435,7 +437,7 @@ static int fuse_readpages(struct file *file, struct address_space *mapping,
435 if (is_bad_inode(inode)) 437 if (is_bad_inode(inode))
436 goto out; 438 goto out;
437 439
438 data.ff = file->private_data; 440 data.file = file;
439 data.inode = inode; 441 data.inode = inode;
440 data.req = fuse_get_req(fc); 442 data.req = fuse_get_req(fc);
441 err = PTR_ERR(data.req); 443 err = PTR_ERR(data.req);
@@ -445,7 +447,7 @@ static int fuse_readpages(struct file *file, struct address_space *mapping,
445 err = read_cache_pages(mapping, pages, fuse_readpages_fill, &data); 447 err = read_cache_pages(mapping, pages, fuse_readpages_fill, &data);
446 if (!err) { 448 if (!err) {
447 if (data.req->num_pages) 449 if (data.req->num_pages)
448 fuse_send_readpages(data.req, data.ff, inode); 450 fuse_send_readpages(data.req, file, inode);
449 else 451 else
450 fuse_put_request(fc, data.req); 452 fuse_put_request(fc, data.req);
451 } 453 }
@@ -472,11 +474,12 @@ static ssize_t fuse_file_aio_read(struct kiocb *iocb, const struct iovec *iov,
472 return generic_file_aio_read(iocb, iov, nr_segs, pos); 474 return generic_file_aio_read(iocb, iov, nr_segs, pos);
473} 475}
474 476
475static void fuse_write_fill(struct fuse_req *req, struct fuse_file *ff, 477static void fuse_write_fill(struct fuse_req *req, struct file *file,
476 struct inode *inode, loff_t pos, size_t count, 478 struct inode *inode, loff_t pos, size_t count,
477 int writepage) 479 int writepage)
478{ 480{
479 struct fuse_conn *fc = get_fuse_conn(inode); 481 struct fuse_conn *fc = get_fuse_conn(inode);
482 struct fuse_file *ff = file->private_data;
480 struct fuse_write_in *inarg = &req->misc.write.in; 483 struct fuse_write_in *inarg = &req->misc.write.in;
481 struct fuse_write_out *outarg = &req->misc.write.out; 484 struct fuse_write_out *outarg = &req->misc.write.out;
482 485
@@ -485,6 +488,7 @@ static void fuse_write_fill(struct fuse_req *req, struct fuse_file *ff,
485 inarg->offset = pos; 488 inarg->offset = pos;
486 inarg->size = count; 489 inarg->size = count;
487 inarg->write_flags = writepage ? FUSE_WRITE_CACHE : 0; 490 inarg->write_flags = writepage ? FUSE_WRITE_CACHE : 0;
491 inarg->flags = file->f_flags;
488 req->in.h.opcode = FUSE_WRITE; 492 req->in.h.opcode = FUSE_WRITE;
489 req->in.h.nodeid = get_node_id(inode); 493 req->in.h.nodeid = get_node_id(inode);
490 req->in.argpages = 1; 494 req->in.argpages = 1;
@@ -505,7 +509,7 @@ static size_t fuse_send_write(struct fuse_req *req, struct file *file,
505 fl_owner_t owner) 509 fl_owner_t owner)
506{ 510{
507 struct fuse_conn *fc = get_fuse_conn(inode); 511 struct fuse_conn *fc = get_fuse_conn(inode);
508 fuse_write_fill(req, file->private_data, inode, pos, count, 0); 512 fuse_write_fill(req, file, inode, pos, count, 0);
509 if (owner != NULL) { 513 if (owner != NULL) {
510 struct fuse_write_in *inarg = &req->misc.write.in; 514 struct fuse_write_in *inarg = &req->misc.write.in;
511 inarg->write_flags |= FUSE_WRITE_LOCKOWNER; 515 inarg->write_flags |= FUSE_WRITE_LOCKOWNER;
diff --git a/fs/fuse/fuse_i.h b/fs/fuse/fuse_i.h
index 19b0129c9811..3ab8a3048e8b 100644
--- a/fs/fuse/fuse_i.h
+++ b/fs/fuse/fuse_i.h
@@ -447,7 +447,7 @@ void fuse_send_forget(struct fuse_conn *fc, struct fuse_req *req,
447/** 447/**
448 * Initialize READ or READDIR request 448 * Initialize READ or READDIR request
449 */ 449 */
450void fuse_read_fill(struct fuse_req *req, struct fuse_file *ff, 450void fuse_read_fill(struct fuse_req *req, struct file *file,
451 struct inode *inode, loff_t pos, size_t count, int opcode); 451 struct inode *inode, loff_t pos, size_t count, int opcode);
452 452
453/** 453/**
diff --git a/include/linux/fuse.h b/include/linux/fuse.h
index d0c437028c80..5c86f1196c3a 100644
--- a/include/linux/fuse.h
+++ b/include/linux/fuse.h
@@ -16,6 +16,7 @@
16 * - add lk_flags in fuse_lk_in 16 * - add lk_flags in fuse_lk_in
17 * - add lock_owner field to fuse_setattr_in, fuse_read_in and fuse_write_in 17 * - add lock_owner field to fuse_setattr_in, fuse_read_in and fuse_write_in
18 * - add blksize field to fuse_attr 18 * - add blksize field to fuse_attr
19 * - add file flags field to fuse_read_in and fuse_write_in
19 */ 20 */
20 21
21#include <asm/types.h> 22#include <asm/types.h>
@@ -280,6 +281,8 @@ struct fuse_read_in {
280 __u32 size; 281 __u32 size;
281 __u32 read_flags; 282 __u32 read_flags;
282 __u64 lock_owner; 283 __u64 lock_owner;
284 __u32 flags;
285 __u32 padding;
283}; 286};
284 287
285#define FUSE_COMPAT_WRITE_IN_SIZE 24 288#define FUSE_COMPAT_WRITE_IN_SIZE 24
@@ -290,6 +293,8 @@ struct fuse_write_in {
290 __u32 size; 293 __u32 size;
291 __u32 write_flags; 294 __u32 write_flags;
292 __u64 lock_owner; 295 __u64 lock_owner;
296 __u32 flags;
297 __u32 padding;
293}; 298};
294 299
295struct fuse_write_out { 300struct fuse_write_out {