diff options
Diffstat (limited to 'fs/fuse/dev.c')
-rw-r--r-- | fs/fuse/dev.c | 83 |
1 files changed, 46 insertions, 37 deletions
diff --git a/fs/fuse/dev.c b/fs/fuse/dev.c index ed19a7d622fa..c8b68ab2e574 100644 --- a/fs/fuse/dev.c +++ b/fs/fuse/dev.c | |||
@@ -19,7 +19,6 @@ | |||
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/aio.h> | ||
23 | 22 | ||
24 | MODULE_ALIAS_MISCDEV(FUSE_MINOR); | 23 | MODULE_ALIAS_MISCDEV(FUSE_MINOR); |
25 | MODULE_ALIAS("devname:fuse"); | 24 | MODULE_ALIAS("devname:fuse"); |
@@ -711,28 +710,26 @@ struct fuse_copy_state { | |||
711 | struct fuse_conn *fc; | 710 | struct fuse_conn *fc; |
712 | int write; | 711 | int write; |
713 | struct fuse_req *req; | 712 | struct fuse_req *req; |
714 | const struct iovec *iov; | 713 | struct iov_iter *iter; |
715 | struct pipe_buffer *pipebufs; | 714 | struct pipe_buffer *pipebufs; |
716 | struct pipe_buffer *currbuf; | 715 | struct pipe_buffer *currbuf; |
717 | struct pipe_inode_info *pipe; | 716 | struct pipe_inode_info *pipe; |
718 | unsigned long nr_segs; | 717 | unsigned long nr_segs; |
719 | unsigned long seglen; | ||
720 | unsigned long addr; | ||
721 | struct page *pg; | 718 | struct page *pg; |
722 | unsigned len; | 719 | unsigned len; |
723 | unsigned offset; | 720 | unsigned offset; |
724 | unsigned move_pages:1; | 721 | unsigned move_pages:1; |
725 | }; | 722 | }; |
726 | 723 | ||
727 | static void fuse_copy_init(struct fuse_copy_state *cs, struct fuse_conn *fc, | 724 | static void fuse_copy_init(struct fuse_copy_state *cs, |
725 | struct fuse_conn *fc, | ||
728 | int write, | 726 | int write, |
729 | const struct iovec *iov, unsigned long nr_segs) | 727 | struct iov_iter *iter) |
730 | { | 728 | { |
731 | memset(cs, 0, sizeof(*cs)); | 729 | memset(cs, 0, sizeof(*cs)); |
732 | cs->fc = fc; | 730 | cs->fc = fc; |
733 | cs->write = write; | 731 | cs->write = write; |
734 | cs->iov = iov; | 732 | cs->iter = iter; |
735 | cs->nr_segs = nr_segs; | ||
736 | } | 733 | } |
737 | 734 | ||
738 | /* Unmap and put previous page of userspace buffer */ | 735 | /* Unmap and put previous page of userspace buffer */ |
@@ -800,22 +797,16 @@ static int fuse_copy_fill(struct fuse_copy_state *cs) | |||
800 | cs->nr_segs++; | 797 | cs->nr_segs++; |
801 | } | 798 | } |
802 | } else { | 799 | } else { |
803 | if (!cs->seglen) { | 800 | size_t off; |
804 | BUG_ON(!cs->nr_segs); | 801 | err = iov_iter_get_pages(cs->iter, &page, PAGE_SIZE, 1, &off); |
805 | cs->seglen = cs->iov[0].iov_len; | ||
806 | cs->addr = (unsigned long) cs->iov[0].iov_base; | ||
807 | cs->iov++; | ||
808 | cs->nr_segs--; | ||
809 | } | ||
810 | err = get_user_pages_fast(cs->addr, 1, cs->write, &page); | ||
811 | if (err < 0) | 802 | if (err < 0) |
812 | return err; | 803 | return err; |
813 | BUG_ON(err != 1); | 804 | BUG_ON(!err); |
805 | cs->len = err; | ||
806 | cs->offset = off; | ||
814 | cs->pg = page; | 807 | cs->pg = page; |
815 | cs->offset = cs->addr % PAGE_SIZE; | 808 | cs->offset = off; |
816 | cs->len = min(PAGE_SIZE - cs->offset, cs->seglen); | 809 | iov_iter_advance(cs->iter, err); |
817 | cs->seglen -= cs->len; | ||
818 | cs->addr += cs->len; | ||
819 | } | 810 | } |
820 | 811 | ||
821 | return lock_request(cs->fc, cs->req); | 812 | return lock_request(cs->fc, cs->req); |
@@ -890,8 +881,8 @@ static int fuse_try_move_page(struct fuse_copy_state *cs, struct page **pagep) | |||
890 | 881 | ||
891 | newpage = buf->page; | 882 | newpage = buf->page; |
892 | 883 | ||
893 | if (WARN_ON(!PageUptodate(newpage))) | 884 | if (!PageUptodate(newpage)) |
894 | return -EIO; | 885 | SetPageUptodate(newpage); |
895 | 886 | ||
896 | ClearPageMappedToDisk(newpage); | 887 | ClearPageMappedToDisk(newpage); |
897 | 888 | ||
@@ -1353,8 +1344,18 @@ static ssize_t fuse_dev_do_read(struct fuse_conn *fc, struct file *file, | |||
1353 | return err; | 1344 | return err; |
1354 | } | 1345 | } |
1355 | 1346 | ||
1356 | static ssize_t fuse_dev_read(struct kiocb *iocb, const struct iovec *iov, | 1347 | static int fuse_dev_open(struct inode *inode, struct file *file) |
1357 | unsigned long nr_segs, loff_t pos) | 1348 | { |
1349 | /* | ||
1350 | * The fuse device's file's private_data is used to hold | ||
1351 | * the fuse_conn(ection) when it is mounted, and is used to | ||
1352 | * keep track of whether the file has been mounted already. | ||
1353 | */ | ||
1354 | file->private_data = NULL; | ||
1355 | return 0; | ||
1356 | } | ||
1357 | |||
1358 | static ssize_t fuse_dev_read(struct kiocb *iocb, struct iov_iter *to) | ||
1358 | { | 1359 | { |
1359 | struct fuse_copy_state cs; | 1360 | struct fuse_copy_state cs; |
1360 | struct file *file = iocb->ki_filp; | 1361 | struct file *file = iocb->ki_filp; |
@@ -1362,9 +1363,12 @@ static ssize_t fuse_dev_read(struct kiocb *iocb, const struct iovec *iov, | |||
1362 | if (!fc) | 1363 | if (!fc) |
1363 | return -EPERM; | 1364 | return -EPERM; |
1364 | 1365 | ||
1365 | fuse_copy_init(&cs, fc, 1, iov, nr_segs); | 1366 | if (!iter_is_iovec(to)) |
1367 | return -EINVAL; | ||
1368 | |||
1369 | fuse_copy_init(&cs, fc, 1, to); | ||
1366 | 1370 | ||
1367 | return fuse_dev_do_read(fc, file, &cs, iov_length(iov, nr_segs)); | 1371 | return fuse_dev_do_read(fc, file, &cs, iov_iter_count(to)); |
1368 | } | 1372 | } |
1369 | 1373 | ||
1370 | static ssize_t fuse_dev_splice_read(struct file *in, loff_t *ppos, | 1374 | static ssize_t fuse_dev_splice_read(struct file *in, loff_t *ppos, |
@@ -1384,7 +1388,7 @@ static ssize_t fuse_dev_splice_read(struct file *in, loff_t *ppos, | |||
1384 | if (!bufs) | 1388 | if (!bufs) |
1385 | return -ENOMEM; | 1389 | return -ENOMEM; |
1386 | 1390 | ||
1387 | fuse_copy_init(&cs, fc, 1, NULL, 0); | 1391 | fuse_copy_init(&cs, fc, 1, NULL); |
1388 | cs.pipebufs = bufs; | 1392 | cs.pipebufs = bufs; |
1389 | cs.pipe = pipe; | 1393 | cs.pipe = pipe; |
1390 | ret = fuse_dev_do_read(fc, in, &cs, len); | 1394 | ret = fuse_dev_do_read(fc, in, &cs, len); |
@@ -1797,6 +1801,9 @@ copy_finish: | |||
1797 | static int fuse_notify(struct fuse_conn *fc, enum fuse_notify_code code, | 1801 | static int fuse_notify(struct fuse_conn *fc, enum fuse_notify_code code, |
1798 | unsigned int size, struct fuse_copy_state *cs) | 1802 | unsigned int size, struct fuse_copy_state *cs) |
1799 | { | 1803 | { |
1804 | /* Don't try to move pages (yet) */ | ||
1805 | cs->move_pages = 0; | ||
1806 | |||
1800 | switch (code) { | 1807 | switch (code) { |
1801 | case FUSE_NOTIFY_POLL: | 1808 | case FUSE_NOTIFY_POLL: |
1802 | return fuse_notify_poll(fc, size, cs); | 1809 | return fuse_notify_poll(fc, size, cs); |
@@ -1957,17 +1964,19 @@ static ssize_t fuse_dev_do_write(struct fuse_conn *fc, | |||
1957 | return err; | 1964 | return err; |
1958 | } | 1965 | } |
1959 | 1966 | ||
1960 | static ssize_t fuse_dev_write(struct kiocb *iocb, const struct iovec *iov, | 1967 | static ssize_t fuse_dev_write(struct kiocb *iocb, struct iov_iter *from) |
1961 | unsigned long nr_segs, loff_t pos) | ||
1962 | { | 1968 | { |
1963 | struct fuse_copy_state cs; | 1969 | struct fuse_copy_state cs; |
1964 | struct fuse_conn *fc = fuse_get_conn(iocb->ki_filp); | 1970 | struct fuse_conn *fc = fuse_get_conn(iocb->ki_filp); |
1965 | if (!fc) | 1971 | if (!fc) |
1966 | return -EPERM; | 1972 | return -EPERM; |
1967 | 1973 | ||
1968 | fuse_copy_init(&cs, fc, 0, iov, nr_segs); | 1974 | if (!iter_is_iovec(from)) |
1975 | return -EINVAL; | ||
1976 | |||
1977 | fuse_copy_init(&cs, fc, 0, from); | ||
1969 | 1978 | ||
1970 | return fuse_dev_do_write(fc, &cs, iov_length(iov, nr_segs)); | 1979 | return fuse_dev_do_write(fc, &cs, iov_iter_count(from)); |
1971 | } | 1980 | } |
1972 | 1981 | ||
1973 | static ssize_t fuse_dev_splice_write(struct pipe_inode_info *pipe, | 1982 | static ssize_t fuse_dev_splice_write(struct pipe_inode_info *pipe, |
@@ -2030,8 +2039,9 @@ static ssize_t fuse_dev_splice_write(struct pipe_inode_info *pipe, | |||
2030 | } | 2039 | } |
2031 | pipe_unlock(pipe); | 2040 | pipe_unlock(pipe); |
2032 | 2041 | ||
2033 | fuse_copy_init(&cs, fc, 0, NULL, nbuf); | 2042 | fuse_copy_init(&cs, fc, 0, NULL); |
2034 | cs.pipebufs = bufs; | 2043 | cs.pipebufs = bufs; |
2044 | cs.nr_segs = nbuf; | ||
2035 | cs.pipe = pipe; | 2045 | cs.pipe = pipe; |
2036 | 2046 | ||
2037 | if (flags & SPLICE_F_MOVE) | 2047 | if (flags & SPLICE_F_MOVE) |
@@ -2217,12 +2227,11 @@ static int fuse_dev_fasync(int fd, struct file *file, int on) | |||
2217 | 2227 | ||
2218 | const struct file_operations fuse_dev_operations = { | 2228 | const struct file_operations fuse_dev_operations = { |
2219 | .owner = THIS_MODULE, | 2229 | .owner = THIS_MODULE, |
2230 | .open = fuse_dev_open, | ||
2220 | .llseek = no_llseek, | 2231 | .llseek = no_llseek, |
2221 | .read = do_sync_read, | 2232 | .read_iter = fuse_dev_read, |
2222 | .aio_read = fuse_dev_read, | ||
2223 | .splice_read = fuse_dev_splice_read, | 2233 | .splice_read = fuse_dev_splice_read, |
2224 | .write = do_sync_write, | 2234 | .write_iter = fuse_dev_write, |
2225 | .aio_write = fuse_dev_write, | ||
2226 | .splice_write = fuse_dev_splice_write, | 2235 | .splice_write = fuse_dev_splice_write, |
2227 | .poll = fuse_dev_poll, | 2236 | .poll = fuse_dev_poll, |
2228 | .release = fuse_dev_release, | 2237 | .release = fuse_dev_release, |