diff options
Diffstat (limited to 'fs/fuse/file.c')
-rw-r--r-- | fs/fuse/file.c | 196 |
1 files changed, 173 insertions, 23 deletions
diff --git a/fs/fuse/file.c b/fs/fuse/file.c index c8224587123f..82a66466a24c 100644 --- a/fs/fuse/file.c +++ b/fs/fuse/file.c | |||
@@ -13,6 +13,7 @@ | |||
13 | #include <linux/kernel.h> | 13 | #include <linux/kernel.h> |
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 | 17 | ||
17 | static const struct file_operations fuse_direct_io_file_operations; | 18 | static const struct file_operations fuse_direct_io_file_operations; |
18 | 19 | ||
@@ -85,18 +86,52 @@ struct fuse_file *fuse_file_get(struct fuse_file *ff) | |||
85 | return ff; | 86 | return ff; |
86 | } | 87 | } |
87 | 88 | ||
89 | static void fuse_release_async(struct work_struct *work) | ||
90 | { | ||
91 | struct fuse_req *req; | ||
92 | struct fuse_conn *fc; | ||
93 | struct path path; | ||
94 | |||
95 | req = container_of(work, struct fuse_req, misc.release.work); | ||
96 | path = req->misc.release.path; | ||
97 | fc = get_fuse_conn(path.dentry->d_inode); | ||
98 | |||
99 | fuse_put_request(fc, req); | ||
100 | path_put(&path); | ||
101 | } | ||
102 | |||
88 | static void fuse_release_end(struct fuse_conn *fc, struct fuse_req *req) | 103 | static void fuse_release_end(struct fuse_conn *fc, struct fuse_req *req) |
89 | { | 104 | { |
90 | path_put(&req->misc.release.path); | 105 | if (fc->destroy_req) { |
106 | /* | ||
107 | * If this is a fuseblk mount, then it's possible that | ||
108 | * releasing the path will result in releasing the | ||
109 | * super block and sending the DESTROY request. If | ||
110 | * the server is single threaded, this would hang. | ||
111 | * For this reason do the path_put() in a separate | ||
112 | * thread. | ||
113 | */ | ||
114 | atomic_inc(&req->count); | ||
115 | INIT_WORK(&req->misc.release.work, fuse_release_async); | ||
116 | schedule_work(&req->misc.release.work); | ||
117 | } else { | ||
118 | path_put(&req->misc.release.path); | ||
119 | } | ||
91 | } | 120 | } |
92 | 121 | ||
93 | static void fuse_file_put(struct fuse_file *ff) | 122 | static void fuse_file_put(struct fuse_file *ff, bool sync) |
94 | { | 123 | { |
95 | if (atomic_dec_and_test(&ff->count)) { | 124 | if (atomic_dec_and_test(&ff->count)) { |
96 | struct fuse_req *req = ff->reserved_req; | 125 | struct fuse_req *req = ff->reserved_req; |
97 | 126 | ||
98 | req->end = fuse_release_end; | 127 | if (sync) { |
99 | fuse_request_send_background(ff->fc, req); | 128 | fuse_request_send(ff->fc, req); |
129 | path_put(&req->misc.release.path); | ||
130 | fuse_put_request(ff->fc, req); | ||
131 | } else { | ||
132 | req->end = fuse_release_end; | ||
133 | fuse_request_send_background(ff->fc, req); | ||
134 | } | ||
100 | kfree(ff); | 135 | kfree(ff); |
101 | } | 136 | } |
102 | } | 137 | } |
@@ -134,6 +169,7 @@ EXPORT_SYMBOL_GPL(fuse_do_open); | |||
134 | void fuse_finish_open(struct inode *inode, struct file *file) | 169 | void fuse_finish_open(struct inode *inode, struct file *file) |
135 | { | 170 | { |
136 | struct fuse_file *ff = file->private_data; | 171 | struct fuse_file *ff = file->private_data; |
172 | struct fuse_conn *fc = get_fuse_conn(inode); | ||
137 | 173 | ||
138 | if (ff->open_flags & FOPEN_DIRECT_IO) | 174 | if (ff->open_flags & FOPEN_DIRECT_IO) |
139 | file->f_op = &fuse_direct_io_file_operations; | 175 | file->f_op = &fuse_direct_io_file_operations; |
@@ -141,6 +177,15 @@ void fuse_finish_open(struct inode *inode, struct file *file) | |||
141 | invalidate_inode_pages2(inode->i_mapping); | 177 | invalidate_inode_pages2(inode->i_mapping); |
142 | if (ff->open_flags & FOPEN_NONSEEKABLE) | 178 | if (ff->open_flags & FOPEN_NONSEEKABLE) |
143 | nonseekable_open(inode, file); | 179 | nonseekable_open(inode, file); |
180 | if (fc->atomic_o_trunc && (file->f_flags & O_TRUNC)) { | ||
181 | struct fuse_inode *fi = get_fuse_inode(inode); | ||
182 | |||
183 | spin_lock(&fc->lock); | ||
184 | fi->attr_version = ++fc->attr_version; | ||
185 | i_size_write(inode, 0); | ||
186 | spin_unlock(&fc->lock); | ||
187 | fuse_invalidate_attr(inode); | ||
188 | } | ||
144 | } | 189 | } |
145 | 190 | ||
146 | int fuse_open_common(struct inode *inode, struct file *file, bool isdir) | 191 | int fuse_open_common(struct inode *inode, struct file *file, bool isdir) |
@@ -177,7 +222,7 @@ static void fuse_prepare_release(struct fuse_file *ff, int flags, int opcode) | |||
177 | rb_erase(&ff->polled_node, &fc->polled_files); | 222 | rb_erase(&ff->polled_node, &fc->polled_files); |
178 | spin_unlock(&fc->lock); | 223 | spin_unlock(&fc->lock); |
179 | 224 | ||
180 | wake_up_interruptible_sync(&ff->poll_wait); | 225 | wake_up_interruptible_all(&ff->poll_wait); |
181 | 226 | ||
182 | inarg->fh = ff->fh; | 227 | inarg->fh = ff->fh; |
183 | inarg->flags = flags; | 228 | inarg->flags = flags; |
@@ -208,8 +253,12 @@ void fuse_release_common(struct file *file, int opcode) | |||
208 | * Normally this will send the RELEASE request, however if | 253 | * Normally this will send the RELEASE request, however if |
209 | * some asynchronous READ or WRITE requests are outstanding, | 254 | * some asynchronous READ or WRITE requests are outstanding, |
210 | * the sending will be delayed. | 255 | * the sending will be delayed. |
256 | * | ||
257 | * Make the release synchronous if this is a fuseblk mount, | ||
258 | * synchronous RELEASE is allowed (and desirable) in this case | ||
259 | * because the server can be trusted not to screw up. | ||
211 | */ | 260 | */ |
212 | fuse_file_put(ff); | 261 | fuse_file_put(ff, ff->fc->destroy_req != NULL); |
213 | } | 262 | } |
214 | 263 | ||
215 | static int fuse_open(struct inode *inode, struct file *file) | 264 | static int fuse_open(struct inode *inode, struct file *file) |
@@ -474,7 +523,7 @@ static int fuse_readpage(struct file *file, struct page *page) | |||
474 | goto out; | 523 | goto out; |
475 | 524 | ||
476 | /* | 525 | /* |
477 | * Page writeback can extend beyond the liftime of the | 526 | * Page writeback can extend beyond the lifetime of the |
478 | * page-cache page, so make sure we read a properly synced | 527 | * page-cache page, so make sure we read a properly synced |
479 | * page. | 528 | * page. |
480 | */ | 529 | */ |
@@ -547,7 +596,7 @@ static void fuse_readpages_end(struct fuse_conn *fc, struct fuse_req *req) | |||
547 | page_cache_release(page); | 596 | page_cache_release(page); |
548 | } | 597 | } |
549 | if (req->ff) | 598 | if (req->ff) |
550 | fuse_file_put(req->ff); | 599 | fuse_file_put(req->ff, false); |
551 | } | 600 | } |
552 | 601 | ||
553 | static void fuse_send_readpages(struct fuse_req *req, struct file *file) | 602 | static void fuse_send_readpages(struct fuse_req *req, struct file *file) |
@@ -1126,7 +1175,7 @@ static ssize_t fuse_direct_write(struct file *file, const char __user *buf, | |||
1126 | static void fuse_writepage_free(struct fuse_conn *fc, struct fuse_req *req) | 1175 | static void fuse_writepage_free(struct fuse_conn *fc, struct fuse_req *req) |
1127 | { | 1176 | { |
1128 | __free_page(req->pages[0]); | 1177 | __free_page(req->pages[0]); |
1129 | fuse_file_put(req->ff); | 1178 | fuse_file_put(req->ff, false); |
1130 | } | 1179 | } |
1131 | 1180 | ||
1132 | static void fuse_writepage_finish(struct fuse_conn *fc, struct fuse_req *req) | 1181 | static void fuse_writepage_finish(struct fuse_conn *fc, struct fuse_req *req) |
@@ -1618,6 +1667,94 @@ static int fuse_ioctl_copy_user(struct page **pages, struct iovec *iov, | |||
1618 | } | 1667 | } |
1619 | 1668 | ||
1620 | /* | 1669 | /* |
1670 | * CUSE servers compiled on 32bit broke on 64bit kernels because the | ||
1671 | * ABI was defined to be 'struct iovec' which is different on 32bit | ||
1672 | * and 64bit. Fortunately we can determine which structure the server | ||
1673 | * used from the size of the reply. | ||
1674 | */ | ||
1675 | static int fuse_copy_ioctl_iovec_old(struct iovec *dst, void *src, | ||
1676 | size_t transferred, unsigned count, | ||
1677 | bool is_compat) | ||
1678 | { | ||
1679 | #ifdef CONFIG_COMPAT | ||
1680 | if (count * sizeof(struct compat_iovec) == transferred) { | ||
1681 | struct compat_iovec *ciov = src; | ||
1682 | unsigned i; | ||
1683 | |||
1684 | /* | ||
1685 | * With this interface a 32bit server cannot support | ||
1686 | * non-compat (i.e. ones coming from 64bit apps) ioctl | ||
1687 | * requests | ||
1688 | */ | ||
1689 | if (!is_compat) | ||
1690 | return -EINVAL; | ||
1691 | |||
1692 | for (i = 0; i < count; i++) { | ||
1693 | dst[i].iov_base = compat_ptr(ciov[i].iov_base); | ||
1694 | dst[i].iov_len = ciov[i].iov_len; | ||
1695 | } | ||
1696 | return 0; | ||
1697 | } | ||
1698 | #endif | ||
1699 | |||
1700 | if (count * sizeof(struct iovec) != transferred) | ||
1701 | return -EIO; | ||
1702 | |||
1703 | memcpy(dst, src, transferred); | ||
1704 | return 0; | ||
1705 | } | ||
1706 | |||
1707 | /* Make sure iov_length() won't overflow */ | ||
1708 | static int fuse_verify_ioctl_iov(struct iovec *iov, size_t count) | ||
1709 | { | ||
1710 | size_t n; | ||
1711 | u32 max = FUSE_MAX_PAGES_PER_REQ << PAGE_SHIFT; | ||
1712 | |||
1713 | for (n = 0; n < count; n++) { | ||
1714 | if (iov->iov_len > (size_t) max) | ||
1715 | return -ENOMEM; | ||
1716 | max -= iov->iov_len; | ||
1717 | } | ||
1718 | return 0; | ||
1719 | } | ||
1720 | |||
1721 | static int fuse_copy_ioctl_iovec(struct fuse_conn *fc, struct iovec *dst, | ||
1722 | void *src, size_t transferred, unsigned count, | ||
1723 | bool is_compat) | ||
1724 | { | ||
1725 | unsigned i; | ||
1726 | struct fuse_ioctl_iovec *fiov = src; | ||
1727 | |||
1728 | if (fc->minor < 16) { | ||
1729 | return fuse_copy_ioctl_iovec_old(dst, src, transferred, | ||
1730 | count, is_compat); | ||
1731 | } | ||
1732 | |||
1733 | if (count * sizeof(struct fuse_ioctl_iovec) != transferred) | ||
1734 | return -EIO; | ||
1735 | |||
1736 | for (i = 0; i < count; i++) { | ||
1737 | /* Did the server supply an inappropriate value? */ | ||
1738 | if (fiov[i].base != (unsigned long) fiov[i].base || | ||
1739 | fiov[i].len != (unsigned long) fiov[i].len) | ||
1740 | return -EIO; | ||
1741 | |||
1742 | dst[i].iov_base = (void __user *) (unsigned long) fiov[i].base; | ||
1743 | dst[i].iov_len = (size_t) fiov[i].len; | ||
1744 | |||
1745 | #ifdef CONFIG_COMPAT | ||
1746 | if (is_compat && | ||
1747 | (ptr_to_compat(dst[i].iov_base) != fiov[i].base || | ||
1748 | (compat_size_t) dst[i].iov_len != fiov[i].len)) | ||
1749 | return -EIO; | ||
1750 | #endif | ||
1751 | } | ||
1752 | |||
1753 | return 0; | ||
1754 | } | ||
1755 | |||
1756 | |||
1757 | /* | ||
1621 | * For ioctls, there is no generic way to determine how much memory | 1758 | * For ioctls, there is no generic way to determine how much memory |
1622 | * needs to be read and/or written. Furthermore, ioctls are allowed | 1759 | * needs to be read and/or written. Furthermore, ioctls are allowed |
1623 | * to dereference the passed pointer, so the parameter requires deep | 1760 | * to dereference the passed pointer, so the parameter requires deep |
@@ -1677,18 +1814,25 @@ long fuse_do_ioctl(struct file *file, unsigned int cmd, unsigned long arg, | |||
1677 | struct fuse_ioctl_out outarg; | 1814 | struct fuse_ioctl_out outarg; |
1678 | struct fuse_req *req = NULL; | 1815 | struct fuse_req *req = NULL; |
1679 | struct page **pages = NULL; | 1816 | struct page **pages = NULL; |
1680 | struct page *iov_page = NULL; | 1817 | struct iovec *iov_page = NULL; |
1681 | struct iovec *in_iov = NULL, *out_iov = NULL; | 1818 | struct iovec *in_iov = NULL, *out_iov = NULL; |
1682 | unsigned int in_iovs = 0, out_iovs = 0, num_pages = 0, max_pages; | 1819 | unsigned int in_iovs = 0, out_iovs = 0, num_pages = 0, max_pages; |
1683 | size_t in_size, out_size, transferred; | 1820 | size_t in_size, out_size, transferred; |
1684 | int err; | 1821 | int err; |
1685 | 1822 | ||
1823 | #if BITS_PER_LONG == 32 | ||
1824 | inarg.flags |= FUSE_IOCTL_32BIT; | ||
1825 | #else | ||
1826 | if (flags & FUSE_IOCTL_COMPAT) | ||
1827 | inarg.flags |= FUSE_IOCTL_32BIT; | ||
1828 | #endif | ||
1829 | |||
1686 | /* assume all the iovs returned by client always fits in a page */ | 1830 | /* assume all the iovs returned by client always fits in a page */ |
1687 | BUILD_BUG_ON(sizeof(struct iovec) * FUSE_IOCTL_MAX_IOV > PAGE_SIZE); | 1831 | BUILD_BUG_ON(sizeof(struct fuse_ioctl_iovec) * FUSE_IOCTL_MAX_IOV > PAGE_SIZE); |
1688 | 1832 | ||
1689 | err = -ENOMEM; | 1833 | err = -ENOMEM; |
1690 | pages = kzalloc(sizeof(pages[0]) * FUSE_MAX_PAGES_PER_REQ, GFP_KERNEL); | 1834 | pages = kzalloc(sizeof(pages[0]) * FUSE_MAX_PAGES_PER_REQ, GFP_KERNEL); |
1691 | iov_page = alloc_page(GFP_KERNEL); | 1835 | iov_page = (struct iovec *) __get_free_page(GFP_KERNEL); |
1692 | if (!pages || !iov_page) | 1836 | if (!pages || !iov_page) |
1693 | goto out; | 1837 | goto out; |
1694 | 1838 | ||
@@ -1697,7 +1841,7 @@ long fuse_do_ioctl(struct file *file, unsigned int cmd, unsigned long arg, | |||
1697 | * RETRY from server is not allowed. | 1841 | * RETRY from server is not allowed. |
1698 | */ | 1842 | */ |
1699 | if (!(flags & FUSE_IOCTL_UNRESTRICTED)) { | 1843 | if (!(flags & FUSE_IOCTL_UNRESTRICTED)) { |
1700 | struct iovec *iov = page_address(iov_page); | 1844 | struct iovec *iov = iov_page; |
1701 | 1845 | ||
1702 | iov->iov_base = (void __user *)arg; | 1846 | iov->iov_base = (void __user *)arg; |
1703 | iov->iov_len = _IOC_SIZE(cmd); | 1847 | iov->iov_len = _IOC_SIZE(cmd); |
@@ -1778,7 +1922,7 @@ long fuse_do_ioctl(struct file *file, unsigned int cmd, unsigned long arg, | |||
1778 | 1922 | ||
1779 | /* did it ask for retry? */ | 1923 | /* did it ask for retry? */ |
1780 | if (outarg.flags & FUSE_IOCTL_RETRY) { | 1924 | if (outarg.flags & FUSE_IOCTL_RETRY) { |
1781 | char *vaddr; | 1925 | void *vaddr; |
1782 | 1926 | ||
1783 | /* no retry if in restricted mode */ | 1927 | /* no retry if in restricted mode */ |
1784 | err = -EIO; | 1928 | err = -EIO; |
@@ -1798,18 +1942,25 @@ long fuse_do_ioctl(struct file *file, unsigned int cmd, unsigned long arg, | |||
1798 | in_iovs + out_iovs > FUSE_IOCTL_MAX_IOV) | 1942 | in_iovs + out_iovs > FUSE_IOCTL_MAX_IOV) |
1799 | goto out; | 1943 | goto out; |
1800 | 1944 | ||
1801 | err = -EIO; | ||
1802 | if ((in_iovs + out_iovs) * sizeof(struct iovec) != transferred) | ||
1803 | goto out; | ||
1804 | |||
1805 | /* okay, copy in iovs and retry */ | ||
1806 | vaddr = kmap_atomic(pages[0], KM_USER0); | 1945 | vaddr = kmap_atomic(pages[0], KM_USER0); |
1807 | memcpy(page_address(iov_page), vaddr, transferred); | 1946 | err = fuse_copy_ioctl_iovec(fc, iov_page, vaddr, |
1947 | transferred, in_iovs + out_iovs, | ||
1948 | (flags & FUSE_IOCTL_COMPAT) != 0); | ||
1808 | kunmap_atomic(vaddr, KM_USER0); | 1949 | kunmap_atomic(vaddr, KM_USER0); |
1950 | if (err) | ||
1951 | goto out; | ||
1809 | 1952 | ||
1810 | in_iov = page_address(iov_page); | 1953 | in_iov = iov_page; |
1811 | out_iov = in_iov + in_iovs; | 1954 | out_iov = in_iov + in_iovs; |
1812 | 1955 | ||
1956 | err = fuse_verify_ioctl_iov(in_iov, in_iovs); | ||
1957 | if (err) | ||
1958 | goto out; | ||
1959 | |||
1960 | err = fuse_verify_ioctl_iov(out_iov, out_iovs); | ||
1961 | if (err) | ||
1962 | goto out; | ||
1963 | |||
1813 | goto retry; | 1964 | goto retry; |
1814 | } | 1965 | } |
1815 | 1966 | ||
@@ -1821,8 +1972,7 @@ long fuse_do_ioctl(struct file *file, unsigned int cmd, unsigned long arg, | |||
1821 | out: | 1972 | out: |
1822 | if (req) | 1973 | if (req) |
1823 | fuse_put_request(fc, req); | 1974 | fuse_put_request(fc, req); |
1824 | if (iov_page) | 1975 | free_page((unsigned long) iov_page); |
1825 | __free_page(iov_page); | ||
1826 | while (num_pages) | 1976 | while (num_pages) |
1827 | __free_page(pages[--num_pages]); | 1977 | __free_page(pages[--num_pages]); |
1828 | kfree(pages); | 1978 | kfree(pages); |