diff options
Diffstat (limited to 'fs/fuse/dev.c')
-rw-r--r-- | fs/fuse/dev.c | 92 |
1 files changed, 87 insertions, 5 deletions
diff --git a/fs/fuse/dev.c b/fs/fuse/dev.c index 8fed2ed12f38..cbceacbc0bf9 100644 --- a/fs/fuse/dev.c +++ b/fs/fuse/dev.c | |||
@@ -16,6 +16,7 @@ | |||
16 | #include <linux/pagemap.h> | 16 | #include <linux/pagemap.h> |
17 | #include <linux/file.h> | 17 | #include <linux/file.h> |
18 | #include <linux/slab.h> | 18 | #include <linux/slab.h> |
19 | #include <linux/blkdev.h> | ||
19 | 20 | ||
20 | MODULE_ALIAS_MISCDEV(FUSE_MINOR); | 21 | MODULE_ALIAS_MISCDEV(FUSE_MINOR); |
21 | 22 | ||
@@ -286,8 +287,8 @@ __releases(&fc->lock) | |||
286 | } | 287 | } |
287 | if (fc->num_background == FUSE_CONGESTION_THRESHOLD && | 288 | if (fc->num_background == FUSE_CONGESTION_THRESHOLD && |
288 | fc->connected && fc->bdi_initialized) { | 289 | fc->connected && fc->bdi_initialized) { |
289 | clear_bdi_congested(&fc->bdi, READ); | 290 | clear_bdi_congested(&fc->bdi, BLK_RW_SYNC); |
290 | clear_bdi_congested(&fc->bdi, WRITE); | 291 | clear_bdi_congested(&fc->bdi, BLK_RW_ASYNC); |
291 | } | 292 | } |
292 | fc->num_background--; | 293 | fc->num_background--; |
293 | fc->active_background--; | 294 | fc->active_background--; |
@@ -414,8 +415,8 @@ static void fuse_request_send_nowait_locked(struct fuse_conn *fc, | |||
414 | fc->blocked = 1; | 415 | fc->blocked = 1; |
415 | if (fc->num_background == FUSE_CONGESTION_THRESHOLD && | 416 | if (fc->num_background == FUSE_CONGESTION_THRESHOLD && |
416 | fc->bdi_initialized) { | 417 | fc->bdi_initialized) { |
417 | set_bdi_congested(&fc->bdi, READ); | 418 | set_bdi_congested(&fc->bdi, BLK_RW_SYNC); |
418 | set_bdi_congested(&fc->bdi, WRITE); | 419 | set_bdi_congested(&fc->bdi, BLK_RW_ASYNC); |
419 | } | 420 | } |
420 | list_add_tail(&req->list, &fc->bg_queue); | 421 | list_add_tail(&req->list, &fc->bg_queue); |
421 | flush_bg_queue(fc); | 422 | flush_bg_queue(fc); |
@@ -849,6 +850,81 @@ err: | |||
849 | return err; | 850 | return err; |
850 | } | 851 | } |
851 | 852 | ||
853 | static int fuse_notify_inval_inode(struct fuse_conn *fc, unsigned int size, | ||
854 | struct fuse_copy_state *cs) | ||
855 | { | ||
856 | struct fuse_notify_inval_inode_out outarg; | ||
857 | int err = -EINVAL; | ||
858 | |||
859 | if (size != sizeof(outarg)) | ||
860 | goto err; | ||
861 | |||
862 | err = fuse_copy_one(cs, &outarg, sizeof(outarg)); | ||
863 | if (err) | ||
864 | goto err; | ||
865 | fuse_copy_finish(cs); | ||
866 | |||
867 | down_read(&fc->killsb); | ||
868 | err = -ENOENT; | ||
869 | if (!fc->sb) | ||
870 | goto err_unlock; | ||
871 | |||
872 | err = fuse_reverse_inval_inode(fc->sb, outarg.ino, | ||
873 | outarg.off, outarg.len); | ||
874 | |||
875 | err_unlock: | ||
876 | up_read(&fc->killsb); | ||
877 | return err; | ||
878 | |||
879 | err: | ||
880 | fuse_copy_finish(cs); | ||
881 | return err; | ||
882 | } | ||
883 | |||
884 | static int fuse_notify_inval_entry(struct fuse_conn *fc, unsigned int size, | ||
885 | struct fuse_copy_state *cs) | ||
886 | { | ||
887 | struct fuse_notify_inval_entry_out outarg; | ||
888 | int err = -EINVAL; | ||
889 | char buf[FUSE_NAME_MAX+1]; | ||
890 | struct qstr name; | ||
891 | |||
892 | if (size < sizeof(outarg)) | ||
893 | goto err; | ||
894 | |||
895 | err = fuse_copy_one(cs, &outarg, sizeof(outarg)); | ||
896 | if (err) | ||
897 | goto err; | ||
898 | |||
899 | err = -ENAMETOOLONG; | ||
900 | if (outarg.namelen > FUSE_NAME_MAX) | ||
901 | goto err; | ||
902 | |||
903 | name.name = buf; | ||
904 | name.len = outarg.namelen; | ||
905 | err = fuse_copy_one(cs, buf, outarg.namelen + 1); | ||
906 | if (err) | ||
907 | goto err; | ||
908 | fuse_copy_finish(cs); | ||
909 | buf[outarg.namelen] = 0; | ||
910 | name.hash = full_name_hash(name.name, name.len); | ||
911 | |||
912 | down_read(&fc->killsb); | ||
913 | err = -ENOENT; | ||
914 | if (!fc->sb) | ||
915 | goto err_unlock; | ||
916 | |||
917 | err = fuse_reverse_inval_entry(fc->sb, outarg.parent, &name); | ||
918 | |||
919 | err_unlock: | ||
920 | up_read(&fc->killsb); | ||
921 | return err; | ||
922 | |||
923 | err: | ||
924 | fuse_copy_finish(cs); | ||
925 | return err; | ||
926 | } | ||
927 | |||
852 | static int fuse_notify(struct fuse_conn *fc, enum fuse_notify_code code, | 928 | static int fuse_notify(struct fuse_conn *fc, enum fuse_notify_code code, |
853 | unsigned int size, struct fuse_copy_state *cs) | 929 | unsigned int size, struct fuse_copy_state *cs) |
854 | { | 930 | { |
@@ -856,6 +932,12 @@ static int fuse_notify(struct fuse_conn *fc, enum fuse_notify_code code, | |||
856 | case FUSE_NOTIFY_POLL: | 932 | case FUSE_NOTIFY_POLL: |
857 | return fuse_notify_poll(fc, size, cs); | 933 | return fuse_notify_poll(fc, size, cs); |
858 | 934 | ||
935 | case FUSE_NOTIFY_INVAL_INODE: | ||
936 | return fuse_notify_inval_inode(fc, size, cs); | ||
937 | |||
938 | case FUSE_NOTIFY_INVAL_ENTRY: | ||
939 | return fuse_notify_inval_entry(fc, size, cs); | ||
940 | |||
859 | default: | 941 | default: |
860 | fuse_copy_finish(cs); | 942 | fuse_copy_finish(cs); |
861 | return -EINVAL; | 943 | return -EINVAL; |
@@ -910,7 +992,7 @@ static ssize_t fuse_dev_write(struct kiocb *iocb, const struct iovec *iov, | |||
910 | unsigned long nr_segs, loff_t pos) | 992 | unsigned long nr_segs, loff_t pos) |
911 | { | 993 | { |
912 | int err; | 994 | int err; |
913 | unsigned nbytes = iov_length(iov, nr_segs); | 995 | size_t nbytes = iov_length(iov, nr_segs); |
914 | struct fuse_req *req; | 996 | struct fuse_req *req; |
915 | struct fuse_out_header oh; | 997 | struct fuse_out_header oh; |
916 | struct fuse_copy_state cs; | 998 | struct fuse_copy_state cs; |