diff options
author | Miklos Szeredi <mszeredi@suse.cz> | 2007-11-28 19:22:00 -0500 |
---|---|---|
committer | Linus Torvalds <torvalds@woody.linux-foundation.org> | 2007-11-29 12:24:54 -0500 |
commit | a6643094e73247c1ebd36816f494f631fa7be348 (patch) | |
tree | 11ba2e666b6fea1cdf579616d6a04b0afd24f61c /fs/fuse/file.c | |
parent | 7dca9fd39f7d4605ac178a67bb1772381056917d (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>
Diffstat (limited to 'fs/fuse/file.c')
-rw-r--r-- | fs/fuse/file.c | 26 |
1 files changed, 15 insertions, 11 deletions
diff --git a/fs/fuse/file.c b/fs/fuse/file.c index 474968fbb55..bb05d227cf3 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 | ||
292 | void fuse_read_fill(struct fuse_req *req, struct fuse_file *ff, | 292 | void 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 | ||
379 | static void fuse_send_readpages(struct fuse_req *req, struct fuse_file *ff, | 380 | static 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 | ||
397 | struct fuse_fill_data { | 399 | struct 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 | ||
475 | static void fuse_write_fill(struct fuse_req *req, struct fuse_file *ff, | 477 | static 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; |