diff options
Diffstat (limited to 'fs/fuse')
-rw-r--r-- | fs/fuse/dev.c | 25 | ||||
-rw-r--r-- | fs/fuse/dir.c | 28 | ||||
-rw-r--r-- | fs/fuse/file.c | 131 | ||||
-rw-r--r-- | fs/fuse/fuse_i.h | 11 | ||||
-rw-r--r-- | fs/fuse/inode.c | 13 |
5 files changed, 104 insertions, 104 deletions
diff --git a/fs/fuse/dev.c b/fs/fuse/dev.c index 640fc229df1..c858b5c8320 100644 --- a/fs/fuse/dev.c +++ b/fs/fuse/dev.c | |||
@@ -19,6 +19,7 @@ | |||
19 | #include <linux/pipe_fs_i.h> | 19 | #include <linux/pipe_fs_i.h> |
20 | #include <linux/swap.h> | 20 | #include <linux/swap.h> |
21 | #include <linux/splice.h> | 21 | #include <linux/splice.h> |
22 | #include <linux/freezer.h> | ||
22 | 23 | ||
23 | MODULE_ALIAS_MISCDEV(FUSE_MINOR); | 24 | MODULE_ALIAS_MISCDEV(FUSE_MINOR); |
24 | MODULE_ALIAS("devname:fuse"); | 25 | MODULE_ALIAS("devname:fuse"); |
@@ -258,10 +259,14 @@ void fuse_queue_forget(struct fuse_conn *fc, struct fuse_forget_link *forget, | |||
258 | forget->forget_one.nlookup = nlookup; | 259 | forget->forget_one.nlookup = nlookup; |
259 | 260 | ||
260 | spin_lock(&fc->lock); | 261 | spin_lock(&fc->lock); |
261 | fc->forget_list_tail->next = forget; | 262 | if (fc->connected) { |
262 | fc->forget_list_tail = forget; | 263 | fc->forget_list_tail->next = forget; |
263 | wake_up(&fc->waitq); | 264 | fc->forget_list_tail = forget; |
264 | kill_fasync(&fc->fasync, SIGIO, POLL_IN); | 265 | wake_up(&fc->waitq); |
266 | kill_fasync(&fc->fasync, SIGIO, POLL_IN); | ||
267 | } else { | ||
268 | kfree(forget); | ||
269 | } | ||
265 | spin_unlock(&fc->lock); | 270 | spin_unlock(&fc->lock); |
266 | } | 271 | } |
267 | 272 | ||
@@ -383,7 +388,10 @@ __acquires(fc->lock) | |||
383 | * Wait it out. | 388 | * Wait it out. |
384 | */ | 389 | */ |
385 | spin_unlock(&fc->lock); | 390 | spin_unlock(&fc->lock); |
386 | wait_event(req->waitq, req->state == FUSE_REQ_FINISHED); | 391 | |
392 | while (req->state != FUSE_REQ_FINISHED) | ||
393 | wait_event_freezable(req->waitq, | ||
394 | req->state == FUSE_REQ_FINISHED); | ||
387 | spin_lock(&fc->lock); | 395 | spin_lock(&fc->lock); |
388 | 396 | ||
389 | if (!req->aborted) | 397 | if (!req->aborted) |
@@ -1358,6 +1366,10 @@ static int fuse_notify_inval_entry(struct fuse_conn *fc, unsigned int size, | |||
1358 | if (outarg.namelen > FUSE_NAME_MAX) | 1366 | if (outarg.namelen > FUSE_NAME_MAX) |
1359 | goto err; | 1367 | goto err; |
1360 | 1368 | ||
1369 | err = -EINVAL; | ||
1370 | if (size != sizeof(outarg) + outarg.namelen + 1) | ||
1371 | goto err; | ||
1372 | |||
1361 | name.name = buf; | 1373 | name.name = buf; |
1362 | name.len = outarg.namelen; | 1374 | name.len = outarg.namelen; |
1363 | err = fuse_copy_one(cs, buf, outarg.namelen + 1); | 1375 | err = fuse_copy_one(cs, buf, outarg.namelen + 1); |
@@ -1504,7 +1516,7 @@ static int fuse_retrieve(struct fuse_conn *fc, struct inode *inode, | |||
1504 | else if (outarg->offset + num > file_size) | 1516 | else if (outarg->offset + num > file_size) |
1505 | num = file_size - outarg->offset; | 1517 | num = file_size - outarg->offset; |
1506 | 1518 | ||
1507 | while (num) { | 1519 | while (num && req->num_pages < FUSE_MAX_PAGES_PER_REQ) { |
1508 | struct page *page; | 1520 | struct page *page; |
1509 | unsigned int this_num; | 1521 | unsigned int this_num; |
1510 | 1522 | ||
@@ -1518,6 +1530,7 @@ static int fuse_retrieve(struct fuse_conn *fc, struct inode *inode, | |||
1518 | 1530 | ||
1519 | num -= this_num; | 1531 | num -= this_num; |
1520 | total_len += this_num; | 1532 | total_len += this_num; |
1533 | index++; | ||
1521 | } | 1534 | } |
1522 | req->misc.retrieve_in.offset = outarg->offset; | 1535 | req->misc.retrieve_in.offset = outarg->offset; |
1523 | req->misc.retrieve_in.size = total_len; | 1536 | req->misc.retrieve_in.size = total_len; |
diff --git a/fs/fuse/dir.c b/fs/fuse/dir.c index d5016071459..9f63e493a9b 100644 --- a/fs/fuse/dir.c +++ b/fs/fuse/dir.c | |||
@@ -382,7 +382,7 @@ static int fuse_create_open(struct inode *dir, struct dentry *entry, int mode, | |||
382 | struct fuse_entry_out outentry; | 382 | struct fuse_entry_out outentry; |
383 | struct fuse_file *ff; | 383 | struct fuse_file *ff; |
384 | struct file *file; | 384 | struct file *file; |
385 | int flags = nd->intent.open.flags - 1; | 385 | int flags = nd->intent.open.flags; |
386 | 386 | ||
387 | if (fc->no_create) | 387 | if (fc->no_create) |
388 | return -ENOSYS; | 388 | return -ENOSYS; |
@@ -576,7 +576,7 @@ static int fuse_mknod(struct inode *dir, struct dentry *entry, int mode, | |||
576 | static int fuse_create(struct inode *dir, struct dentry *entry, int mode, | 576 | static int fuse_create(struct inode *dir, struct dentry *entry, int mode, |
577 | struct nameidata *nd) | 577 | struct nameidata *nd) |
578 | { | 578 | { |
579 | if (nd && (nd->flags & LOOKUP_OPEN)) { | 579 | if (nd) { |
580 | int err = fuse_create_open(dir, entry, mode, nd); | 580 | int err = fuse_create_open(dir, entry, mode, nd); |
581 | if (err != -ENOSYS) | 581 | if (err != -ENOSYS) |
582 | return err; | 582 | return err; |
@@ -971,9 +971,9 @@ static int fuse_access(struct inode *inode, int mask) | |||
971 | return err; | 971 | return err; |
972 | } | 972 | } |
973 | 973 | ||
974 | static int fuse_perm_getattr(struct inode *inode, int flags) | 974 | static int fuse_perm_getattr(struct inode *inode, int mask) |
975 | { | 975 | { |
976 | if (flags & IPERM_FLAG_RCU) | 976 | if (mask & MAY_NOT_BLOCK) |
977 | return -ECHILD; | 977 | return -ECHILD; |
978 | 978 | ||
979 | return fuse_do_getattr(inode, NULL, NULL); | 979 | return fuse_do_getattr(inode, NULL, NULL); |
@@ -992,7 +992,7 @@ static int fuse_perm_getattr(struct inode *inode, int flags) | |||
992 | * access request is sent. Execute permission is still checked | 992 | * access request is sent. Execute permission is still checked |
993 | * locally based on file mode. | 993 | * locally based on file mode. |
994 | */ | 994 | */ |
995 | static int fuse_permission(struct inode *inode, int mask, unsigned int flags) | 995 | static int fuse_permission(struct inode *inode, int mask) |
996 | { | 996 | { |
997 | struct fuse_conn *fc = get_fuse_conn(inode); | 997 | struct fuse_conn *fc = get_fuse_conn(inode); |
998 | bool refreshed = false; | 998 | bool refreshed = false; |
@@ -1011,23 +1011,22 @@ static int fuse_permission(struct inode *inode, int mask, unsigned int flags) | |||
1011 | if (fi->i_time < get_jiffies_64()) { | 1011 | if (fi->i_time < get_jiffies_64()) { |
1012 | refreshed = true; | 1012 | refreshed = true; |
1013 | 1013 | ||
1014 | err = fuse_perm_getattr(inode, flags); | 1014 | err = fuse_perm_getattr(inode, mask); |
1015 | if (err) | 1015 | if (err) |
1016 | return err; | 1016 | return err; |
1017 | } | 1017 | } |
1018 | } | 1018 | } |
1019 | 1019 | ||
1020 | if (fc->flags & FUSE_DEFAULT_PERMISSIONS) { | 1020 | if (fc->flags & FUSE_DEFAULT_PERMISSIONS) { |
1021 | err = generic_permission(inode, mask, flags, NULL); | 1021 | err = generic_permission(inode, mask); |
1022 | 1022 | ||
1023 | /* If permission is denied, try to refresh file | 1023 | /* If permission is denied, try to refresh file |
1024 | attributes. This is also needed, because the root | 1024 | attributes. This is also needed, because the root |
1025 | node will at first have no permissions */ | 1025 | node will at first have no permissions */ |
1026 | if (err == -EACCES && !refreshed) { | 1026 | if (err == -EACCES && !refreshed) { |
1027 | err = fuse_perm_getattr(inode, flags); | 1027 | err = fuse_perm_getattr(inode, mask); |
1028 | if (!err) | 1028 | if (!err) |
1029 | err = generic_permission(inode, mask, | 1029 | err = generic_permission(inode, mask); |
1030 | flags, NULL); | ||
1031 | } | 1030 | } |
1032 | 1031 | ||
1033 | /* Note: the opposite of the above test does not | 1032 | /* Note: the opposite of the above test does not |
@@ -1035,7 +1034,7 @@ static int fuse_permission(struct inode *inode, int mask, unsigned int flags) | |||
1035 | noticed immediately, only after the attribute | 1034 | noticed immediately, only after the attribute |
1036 | timeout has expired */ | 1035 | timeout has expired */ |
1037 | } else if (mask & (MAY_ACCESS | MAY_CHDIR)) { | 1036 | } else if (mask & (MAY_ACCESS | MAY_CHDIR)) { |
1038 | if (flags & IPERM_FLAG_RCU) | 1037 | if (mask & MAY_NOT_BLOCK) |
1039 | return -ECHILD; | 1038 | return -ECHILD; |
1040 | 1039 | ||
1041 | err = fuse_access(inode, mask); | 1040 | err = fuse_access(inode, mask); |
@@ -1044,7 +1043,7 @@ static int fuse_permission(struct inode *inode, int mask, unsigned int flags) | |||
1044 | if (refreshed) | 1043 | if (refreshed) |
1045 | return -EACCES; | 1044 | return -EACCES; |
1046 | 1045 | ||
1047 | err = fuse_perm_getattr(inode, flags); | 1046 | err = fuse_perm_getattr(inode, mask); |
1048 | if (!err && !(inode->i_mode & S_IXUGO)) | 1047 | if (!err && !(inode->i_mode & S_IXUGO)) |
1049 | return -EACCES; | 1048 | return -EACCES; |
1050 | } | 1049 | } |
@@ -1177,9 +1176,10 @@ static int fuse_dir_release(struct inode *inode, struct file *file) | |||
1177 | return 0; | 1176 | return 0; |
1178 | } | 1177 | } |
1179 | 1178 | ||
1180 | static int fuse_dir_fsync(struct file *file, int datasync) | 1179 | static int fuse_dir_fsync(struct file *file, loff_t start, loff_t end, |
1180 | int datasync) | ||
1181 | { | 1181 | { |
1182 | return fuse_fsync_common(file, datasync, 1); | 1182 | return fuse_fsync_common(file, start, end, datasync, 1); |
1183 | } | 1183 | } |
1184 | 1184 | ||
1185 | static bool update_mtime(unsigned ivalid) | 1185 | static bool update_mtime(unsigned ivalid) |
diff --git a/fs/fuse/file.c b/fs/fuse/file.c index 82a66466a24..19029e97ca2 100644 --- a/fs/fuse/file.c +++ b/fs/fuse/file.c | |||
@@ -14,6 +14,7 @@ | |||
14 | #include <linux/sched.h> | 14 | #include <linux/sched.h> |
15 | #include <linux/module.h> | 15 | #include <linux/module.h> |
16 | #include <linux/compat.h> | 16 | #include <linux/compat.h> |
17 | #include <linux/swap.h> | ||
17 | 18 | ||
18 | static const struct file_operations fuse_direct_io_file_operations; | 19 | static const struct file_operations fuse_direct_io_file_operations; |
19 | 20 | ||
@@ -245,6 +246,12 @@ void fuse_release_common(struct file *file, int opcode) | |||
245 | req = ff->reserved_req; | 246 | req = ff->reserved_req; |
246 | fuse_prepare_release(ff, file->f_flags, opcode); | 247 | fuse_prepare_release(ff, file->f_flags, opcode); |
247 | 248 | ||
249 | if (ff->flock) { | ||
250 | struct fuse_release_in *inarg = &req->misc.release.in; | ||
251 | inarg->release_flags |= FUSE_RELEASE_FLOCK_UNLOCK; | ||
252 | inarg->lock_owner = fuse_lock_owner_id(ff->fc, | ||
253 | (fl_owner_t) file); | ||
254 | } | ||
248 | /* Hold vfsmount and dentry until release is finished */ | 255 | /* Hold vfsmount and dentry until release is finished */ |
249 | path_get(&file->f_path); | 256 | path_get(&file->f_path); |
250 | req->misc.release.path = file->f_path; | 257 | req->misc.release.path = file->f_path; |
@@ -400,7 +407,8 @@ static void fuse_sync_writes(struct inode *inode) | |||
400 | fuse_release_nowrite(inode); | 407 | fuse_release_nowrite(inode); |
401 | } | 408 | } |
402 | 409 | ||
403 | int fuse_fsync_common(struct file *file, int datasync, int isdir) | 410 | int fuse_fsync_common(struct file *file, loff_t start, loff_t end, |
411 | int datasync, int isdir) | ||
404 | { | 412 | { |
405 | struct inode *inode = file->f_mapping->host; | 413 | struct inode *inode = file->f_mapping->host; |
406 | struct fuse_conn *fc = get_fuse_conn(inode); | 414 | struct fuse_conn *fc = get_fuse_conn(inode); |
@@ -412,9 +420,15 @@ int fuse_fsync_common(struct file *file, int datasync, int isdir) | |||
412 | if (is_bad_inode(inode)) | 420 | if (is_bad_inode(inode)) |
413 | return -EIO; | 421 | return -EIO; |
414 | 422 | ||
423 | err = filemap_write_and_wait_range(inode->i_mapping, start, end); | ||
424 | if (err) | ||
425 | return err; | ||
426 | |||
415 | if ((!isdir && fc->no_fsync) || (isdir && fc->no_fsyncdir)) | 427 | if ((!isdir && fc->no_fsync) || (isdir && fc->no_fsyncdir)) |
416 | return 0; | 428 | return 0; |
417 | 429 | ||
430 | mutex_lock(&inode->i_mutex); | ||
431 | |||
418 | /* | 432 | /* |
419 | * Start writeback against all dirty pages of the inode, then | 433 | * Start writeback against all dirty pages of the inode, then |
420 | * wait for all outstanding writes, before sending the FSYNC | 434 | * wait for all outstanding writes, before sending the FSYNC |
@@ -422,13 +436,15 @@ int fuse_fsync_common(struct file *file, int datasync, int isdir) | |||
422 | */ | 436 | */ |
423 | err = write_inode_now(inode, 0); | 437 | err = write_inode_now(inode, 0); |
424 | if (err) | 438 | if (err) |
425 | return err; | 439 | goto out; |
426 | 440 | ||
427 | fuse_sync_writes(inode); | 441 | fuse_sync_writes(inode); |
428 | 442 | ||
429 | req = fuse_get_req(fc); | 443 | req = fuse_get_req(fc); |
430 | if (IS_ERR(req)) | 444 | if (IS_ERR(req)) { |
431 | return PTR_ERR(req); | 445 | err = PTR_ERR(req); |
446 | goto out; | ||
447 | } | ||
432 | 448 | ||
433 | memset(&inarg, 0, sizeof(inarg)); | 449 | memset(&inarg, 0, sizeof(inarg)); |
434 | inarg.fh = ff->fh; | 450 | inarg.fh = ff->fh; |
@@ -448,12 +464,15 @@ int fuse_fsync_common(struct file *file, int datasync, int isdir) | |||
448 | fc->no_fsync = 1; | 464 | fc->no_fsync = 1; |
449 | err = 0; | 465 | err = 0; |
450 | } | 466 | } |
467 | out: | ||
468 | mutex_unlock(&inode->i_mutex); | ||
451 | return err; | 469 | return err; |
452 | } | 470 | } |
453 | 471 | ||
454 | static int fuse_fsync(struct file *file, int datasync) | 472 | static int fuse_fsync(struct file *file, loff_t start, loff_t end, |
473 | int datasync) | ||
455 | { | 474 | { |
456 | return fuse_fsync_common(file, datasync, 0); | 475 | return fuse_fsync_common(file, start, end, datasync, 0); |
457 | } | 476 | } |
458 | 477 | ||
459 | void fuse_read_fill(struct fuse_req *req, struct file *file, loff_t pos, | 478 | void fuse_read_fill(struct fuse_req *req, struct file *file, loff_t pos, |
@@ -743,18 +762,6 @@ static size_t fuse_send_write(struct fuse_req *req, struct file *file, | |||
743 | return req->misc.write.out.size; | 762 | return req->misc.write.out.size; |
744 | } | 763 | } |
745 | 764 | ||
746 | static int fuse_write_begin(struct file *file, struct address_space *mapping, | ||
747 | loff_t pos, unsigned len, unsigned flags, | ||
748 | struct page **pagep, void **fsdata) | ||
749 | { | ||
750 | pgoff_t index = pos >> PAGE_CACHE_SHIFT; | ||
751 | |||
752 | *pagep = grab_cache_page_write_begin(mapping, index, flags); | ||
753 | if (!*pagep) | ||
754 | return -ENOMEM; | ||
755 | return 0; | ||
756 | } | ||
757 | |||
758 | void fuse_write_update_size(struct inode *inode, loff_t pos) | 765 | void fuse_write_update_size(struct inode *inode, loff_t pos) |
759 | { | 766 | { |
760 | struct fuse_conn *fc = get_fuse_conn(inode); | 767 | struct fuse_conn *fc = get_fuse_conn(inode); |
@@ -767,62 +774,6 @@ void fuse_write_update_size(struct inode *inode, loff_t pos) | |||
767 | spin_unlock(&fc->lock); | 774 | spin_unlock(&fc->lock); |
768 | } | 775 | } |
769 | 776 | ||
770 | static int fuse_buffered_write(struct file *file, struct inode *inode, | ||
771 | loff_t pos, unsigned count, struct page *page) | ||
772 | { | ||
773 | int err; | ||
774 | size_t nres; | ||
775 | struct fuse_conn *fc = get_fuse_conn(inode); | ||
776 | unsigned offset = pos & (PAGE_CACHE_SIZE - 1); | ||
777 | struct fuse_req *req; | ||
778 | |||
779 | if (is_bad_inode(inode)) | ||
780 | return -EIO; | ||
781 | |||
782 | /* | ||
783 | * Make sure writepages on the same page are not mixed up with | ||
784 | * plain writes. | ||
785 | */ | ||
786 | fuse_wait_on_page_writeback(inode, page->index); | ||
787 | |||
788 | req = fuse_get_req(fc); | ||
789 | if (IS_ERR(req)) | ||
790 | return PTR_ERR(req); | ||
791 | |||
792 | req->in.argpages = 1; | ||
793 | req->num_pages = 1; | ||
794 | req->pages[0] = page; | ||
795 | req->page_offset = offset; | ||
796 | nres = fuse_send_write(req, file, pos, count, NULL); | ||
797 | err = req->out.h.error; | ||
798 | fuse_put_request(fc, req); | ||
799 | if (!err && !nres) | ||
800 | err = -EIO; | ||
801 | if (!err) { | ||
802 | pos += nres; | ||
803 | fuse_write_update_size(inode, pos); | ||
804 | if (count == PAGE_CACHE_SIZE) | ||
805 | SetPageUptodate(page); | ||
806 | } | ||
807 | fuse_invalidate_attr(inode); | ||
808 | return err ? err : nres; | ||
809 | } | ||
810 | |||
811 | static int fuse_write_end(struct file *file, struct address_space *mapping, | ||
812 | loff_t pos, unsigned len, unsigned copied, | ||
813 | struct page *page, void *fsdata) | ||
814 | { | ||
815 | struct inode *inode = mapping->host; | ||
816 | int res = 0; | ||
817 | |||
818 | if (copied) | ||
819 | res = fuse_buffered_write(file, inode, pos, copied, page); | ||
820 | |||
821 | unlock_page(page); | ||
822 | page_cache_release(page); | ||
823 | return res; | ||
824 | } | ||
825 | |||
826 | static size_t fuse_send_write_pages(struct fuse_req *req, struct file *file, | 777 | static size_t fuse_send_write_pages(struct fuse_req *req, struct file *file, |
827 | struct inode *inode, loff_t pos, | 778 | struct inode *inode, loff_t pos, |
828 | size_t count) | 779 | size_t count) |
@@ -896,6 +847,8 @@ static ssize_t fuse_fill_write_pages(struct fuse_req *req, | |||
896 | pagefault_enable(); | 847 | pagefault_enable(); |
897 | flush_dcache_page(page); | 848 | flush_dcache_page(page); |
898 | 849 | ||
850 | mark_page_accessed(page); | ||
851 | |||
899 | if (!tmp) { | 852 | if (!tmp) { |
900 | unlock_page(page); | 853 | unlock_page(page); |
901 | page_cache_release(page); | 854 | page_cache_release(page); |
@@ -1495,7 +1448,7 @@ static int fuse_setlk(struct file *file, struct file_lock *fl, int flock) | |||
1495 | pid_t pid = fl->fl_type != F_UNLCK ? current->tgid : 0; | 1448 | pid_t pid = fl->fl_type != F_UNLCK ? current->tgid : 0; |
1496 | int err; | 1449 | int err; |
1497 | 1450 | ||
1498 | if (fl->fl_lmops && fl->fl_lmops->fl_grant) { | 1451 | if (fl->fl_lmops && fl->fl_lmops->lm_grant) { |
1499 | /* NLM needs asynchronous locks, which we don't support yet */ | 1452 | /* NLM needs asynchronous locks, which we don't support yet */ |
1500 | return -ENOLCK; | 1453 | return -ENOLCK; |
1501 | } | 1454 | } |
@@ -1547,11 +1500,14 @@ static int fuse_file_flock(struct file *file, int cmd, struct file_lock *fl) | |||
1547 | struct fuse_conn *fc = get_fuse_conn(inode); | 1500 | struct fuse_conn *fc = get_fuse_conn(inode); |
1548 | int err; | 1501 | int err; |
1549 | 1502 | ||
1550 | if (fc->no_lock) { | 1503 | if (fc->no_flock) { |
1551 | err = flock_lock_file_wait(file, fl); | 1504 | err = flock_lock_file_wait(file, fl); |
1552 | } else { | 1505 | } else { |
1506 | struct fuse_file *ff = file->private_data; | ||
1507 | |||
1553 | /* emulate flock with POSIX locks */ | 1508 | /* emulate flock with POSIX locks */ |
1554 | fl->fl_owner = (fl_owner_t) file; | 1509 | fl->fl_owner = (fl_owner_t) file; |
1510 | ff->flock = true; | ||
1555 | err = fuse_setlk(file, fl, 1); | 1511 | err = fuse_setlk(file, fl, 1); |
1556 | } | 1512 | } |
1557 | 1513 | ||
@@ -1600,15 +1556,32 @@ static loff_t fuse_file_llseek(struct file *file, loff_t offset, int origin) | |||
1600 | struct inode *inode = file->f_path.dentry->d_inode; | 1556 | struct inode *inode = file->f_path.dentry->d_inode; |
1601 | 1557 | ||
1602 | mutex_lock(&inode->i_mutex); | 1558 | mutex_lock(&inode->i_mutex); |
1603 | switch (origin) { | 1559 | if (origin != SEEK_CUR && origin != SEEK_SET) { |
1604 | case SEEK_END: | ||
1605 | retval = fuse_update_attributes(inode, NULL, file, NULL); | 1560 | retval = fuse_update_attributes(inode, NULL, file, NULL); |
1606 | if (retval) | 1561 | if (retval) |
1607 | goto exit; | 1562 | goto exit; |
1563 | } | ||
1564 | |||
1565 | switch (origin) { | ||
1566 | case SEEK_END: | ||
1608 | offset += i_size_read(inode); | 1567 | offset += i_size_read(inode); |
1609 | break; | 1568 | break; |
1610 | case SEEK_CUR: | 1569 | case SEEK_CUR: |
1611 | offset += file->f_pos; | 1570 | offset += file->f_pos; |
1571 | break; | ||
1572 | case SEEK_DATA: | ||
1573 | if (offset >= i_size_read(inode)) { | ||
1574 | retval = -ENXIO; | ||
1575 | goto exit; | ||
1576 | } | ||
1577 | break; | ||
1578 | case SEEK_HOLE: | ||
1579 | if (offset >= i_size_read(inode)) { | ||
1580 | retval = -ENXIO; | ||
1581 | goto exit; | ||
1582 | } | ||
1583 | offset = i_size_read(inode); | ||
1584 | break; | ||
1612 | } | 1585 | } |
1613 | retval = -EINVAL; | 1586 | retval = -EINVAL; |
1614 | if (offset >= 0 && offset <= inode->i_sb->s_maxbytes) { | 1587 | if (offset >= 0 && offset <= inode->i_sb->s_maxbytes) { |
@@ -2172,8 +2145,6 @@ static const struct address_space_operations fuse_file_aops = { | |||
2172 | .readpage = fuse_readpage, | 2145 | .readpage = fuse_readpage, |
2173 | .writepage = fuse_writepage, | 2146 | .writepage = fuse_writepage, |
2174 | .launder_page = fuse_launder_page, | 2147 | .launder_page = fuse_launder_page, |
2175 | .write_begin = fuse_write_begin, | ||
2176 | .write_end = fuse_write_end, | ||
2177 | .readpages = fuse_readpages, | 2148 | .readpages = fuse_readpages, |
2178 | .set_page_dirty = __set_page_dirty_nobuffers, | 2149 | .set_page_dirty = __set_page_dirty_nobuffers, |
2179 | .bmap = fuse_bmap, | 2150 | .bmap = fuse_bmap, |
diff --git a/fs/fuse/fuse_i.h b/fs/fuse/fuse_i.h index b788becada7..cf6db0a9321 100644 --- a/fs/fuse/fuse_i.h +++ b/fs/fuse/fuse_i.h | |||
@@ -135,6 +135,9 @@ struct fuse_file { | |||
135 | 135 | ||
136 | /** Wait queue head for poll */ | 136 | /** Wait queue head for poll */ |
137 | wait_queue_head_t poll_wait; | 137 | wait_queue_head_t poll_wait; |
138 | |||
139 | /** Has flock been performed on this file? */ | ||
140 | bool flock:1; | ||
138 | }; | 141 | }; |
139 | 142 | ||
140 | /** One input argument of a request */ | 143 | /** One input argument of a request */ |
@@ -448,7 +451,7 @@ struct fuse_conn { | |||
448 | /** Is removexattr not implemented by fs? */ | 451 | /** Is removexattr not implemented by fs? */ |
449 | unsigned no_removexattr:1; | 452 | unsigned no_removexattr:1; |
450 | 453 | ||
451 | /** Are file locking primitives not implemented by fs? */ | 454 | /** Are posix file locking primitives not implemented by fs? */ |
452 | unsigned no_lock:1; | 455 | unsigned no_lock:1; |
453 | 456 | ||
454 | /** Is access not implemented by fs? */ | 457 | /** Is access not implemented by fs? */ |
@@ -472,6 +475,9 @@ struct fuse_conn { | |||
472 | /** Don't apply umask to creation modes */ | 475 | /** Don't apply umask to creation modes */ |
473 | unsigned dont_mask:1; | 476 | unsigned dont_mask:1; |
474 | 477 | ||
478 | /** Are BSD file locking primitives not implemented by fs? */ | ||
479 | unsigned no_flock:1; | ||
480 | |||
475 | /** The number of requests waiting for completion */ | 481 | /** The number of requests waiting for completion */ |
476 | atomic_t num_waiting; | 482 | atomic_t num_waiting; |
477 | 483 | ||
@@ -589,7 +595,8 @@ void fuse_release_common(struct file *file, int opcode); | |||
589 | /** | 595 | /** |
590 | * Send FSYNC or FSYNCDIR request | 596 | * Send FSYNC or FSYNCDIR request |
591 | */ | 597 | */ |
592 | int fuse_fsync_common(struct file *file, int datasync, int isdir); | 598 | int fuse_fsync_common(struct file *file, loff_t start, loff_t end, |
599 | int datasync, int isdir); | ||
593 | 600 | ||
594 | /** | 601 | /** |
595 | * Notify poll wakeup | 602 | * Notify poll wakeup |
diff --git a/fs/fuse/inode.c b/fs/fuse/inode.c index 38f84cd48b6..add96f6ffda 100644 --- a/fs/fuse/inode.c +++ b/fs/fuse/inode.c | |||
@@ -71,7 +71,7 @@ struct fuse_mount_data { | |||
71 | unsigned blksize; | 71 | unsigned blksize; |
72 | }; | 72 | }; |
73 | 73 | ||
74 | struct fuse_forget_link *fuse_alloc_forget() | 74 | struct fuse_forget_link *fuse_alloc_forget(void) |
75 | { | 75 | { |
76 | return kzalloc(sizeof(struct fuse_forget_link), GFP_KERNEL); | 76 | return kzalloc(sizeof(struct fuse_forget_link), GFP_KERNEL); |
77 | } | 77 | } |
@@ -809,6 +809,13 @@ static void process_init_reply(struct fuse_conn *fc, struct fuse_req *req) | |||
809 | fc->async_read = 1; | 809 | fc->async_read = 1; |
810 | if (!(arg->flags & FUSE_POSIX_LOCKS)) | 810 | if (!(arg->flags & FUSE_POSIX_LOCKS)) |
811 | fc->no_lock = 1; | 811 | fc->no_lock = 1; |
812 | if (arg->minor >= 17) { | ||
813 | if (!(arg->flags & FUSE_FLOCK_LOCKS)) | ||
814 | fc->no_flock = 1; | ||
815 | } else { | ||
816 | if (!(arg->flags & FUSE_POSIX_LOCKS)) | ||
817 | fc->no_flock = 1; | ||
818 | } | ||
812 | if (arg->flags & FUSE_ATOMIC_O_TRUNC) | 819 | if (arg->flags & FUSE_ATOMIC_O_TRUNC) |
813 | fc->atomic_o_trunc = 1; | 820 | fc->atomic_o_trunc = 1; |
814 | if (arg->minor >= 9) { | 821 | if (arg->minor >= 9) { |
@@ -823,6 +830,7 @@ static void process_init_reply(struct fuse_conn *fc, struct fuse_req *req) | |||
823 | } else { | 830 | } else { |
824 | ra_pages = fc->max_read / PAGE_CACHE_SIZE; | 831 | ra_pages = fc->max_read / PAGE_CACHE_SIZE; |
825 | fc->no_lock = 1; | 832 | fc->no_lock = 1; |
833 | fc->no_flock = 1; | ||
826 | } | 834 | } |
827 | 835 | ||
828 | fc->bdi.ra_pages = min(fc->bdi.ra_pages, ra_pages); | 836 | fc->bdi.ra_pages = min(fc->bdi.ra_pages, ra_pages); |
@@ -843,7 +851,8 @@ static void fuse_send_init(struct fuse_conn *fc, struct fuse_req *req) | |||
843 | arg->minor = FUSE_KERNEL_MINOR_VERSION; | 851 | arg->minor = FUSE_KERNEL_MINOR_VERSION; |
844 | arg->max_readahead = fc->bdi.ra_pages * PAGE_CACHE_SIZE; | 852 | arg->max_readahead = fc->bdi.ra_pages * PAGE_CACHE_SIZE; |
845 | arg->flags |= FUSE_ASYNC_READ | FUSE_POSIX_LOCKS | FUSE_ATOMIC_O_TRUNC | | 853 | arg->flags |= FUSE_ASYNC_READ | FUSE_POSIX_LOCKS | FUSE_ATOMIC_O_TRUNC | |
846 | FUSE_EXPORT_SUPPORT | FUSE_BIG_WRITES | FUSE_DONT_MASK; | 854 | FUSE_EXPORT_SUPPORT | FUSE_BIG_WRITES | FUSE_DONT_MASK | |
855 | FUSE_FLOCK_LOCKS; | ||
847 | req->in.h.opcode = FUSE_INIT; | 856 | req->in.h.opcode = FUSE_INIT; |
848 | req->in.numargs = 1; | 857 | req->in.numargs = 1; |
849 | req->in.args[0].size = sizeof(*arg); | 858 | req->in.args[0].size = sizeof(*arg); |