Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

Merge tag 'fuse-fixes-5.8-rc6' of git://git.kernel.org/pub/scm/linux/kernel/git/mszeredi/fuse into master

Pull fuse fixes from Miklos Szeredi:

- two regressions in this cycle caused by the conversion of writepage
list to an rb_tree

- two regressions in v5.4 cause by the conversion to the new mount API

- saner behavior of fsconfig(2) for the reconfigure case

- an ancient issue with FS_IOC_{GET,SET}FLAGS ioctls

* tag 'fuse-fixes-5.8-rc6' of git://git.kernel.org/pub/scm/linux/kernel/git/mszeredi/fuse:
fuse: Fix parameter for FS_IOC_{GET,SET}FLAGS
fuse: don't ignore errors from fuse_writepages_fill()
fuse: clean up condition for writepage sending
fuse: reject options on reconfigure via fsconfig(2)
fuse: ignore 'data' argument of mount(..., MS_REMOUNT)
fuse: use ->reconfigure() instead of ->remount_fs()
fuse: fix warning in tree_insert() and clean up writepage insertion
fuse: move rb_erase() before tree_insert()

+96 -57
+78 -54
fs/fuse/file.c
··· 18 18 #include <linux/swap.h> 19 19 #include <linux/falloc.h> 20 20 #include <linux/uio.h> 21 + #include <linux/fs.h> 21 22 22 23 static struct page **fuse_pages_alloc(unsigned int npages, gfp_t flags, 23 24 struct fuse_page_desc **desc) ··· 1587 1586 struct backing_dev_info *bdi = inode_to_bdi(inode); 1588 1587 int i; 1589 1588 1590 - rb_erase(&wpa->writepages_entry, &fi->writepages); 1591 1589 for (i = 0; i < ap->num_pages; i++) { 1592 1590 dec_wb_stat(&bdi->wb, WB_WRITEBACK); 1593 1591 dec_node_page_state(ap->pages[i], NR_WRITEBACK_TEMP); ··· 1637 1637 1638 1638 out_free: 1639 1639 fi->writectr--; 1640 + rb_erase(&wpa->writepages_entry, &fi->writepages); 1640 1641 fuse_writepage_finish(fc, wpa); 1641 1642 spin_unlock(&fi->lock); 1642 1643 ··· 1675 1674 } 1676 1675 } 1677 1676 1678 - static void tree_insert(struct rb_root *root, struct fuse_writepage_args *wpa) 1677 + static struct fuse_writepage_args *fuse_insert_writeback(struct rb_root *root, 1678 + struct fuse_writepage_args *wpa) 1679 1679 { 1680 1680 pgoff_t idx_from = wpa->ia.write.in.offset >> PAGE_SHIFT; 1681 1681 pgoff_t idx_to = idx_from + wpa->ia.ap.num_pages - 1; ··· 1699 1697 else if (idx_to < curr_index) 1700 1698 p = &(*p)->rb_left; 1701 1699 else 1702 - return (void) WARN_ON(true); 1700 + return curr; 1703 1701 } 1704 1702 1705 1703 rb_link_node(&wpa->writepages_entry, parent, p); 1706 1704 rb_insert_color(&wpa->writepages_entry, root); 1705 + return NULL; 1706 + } 1707 + 1708 + static void tree_insert(struct rb_root *root, struct fuse_writepage_args *wpa) 1709 + { 1710 + WARN_ON(fuse_insert_writeback(root, wpa)); 1707 1711 } 1708 1712 1709 1713 static void fuse_writepage_end(struct fuse_conn *fc, struct fuse_args *args, ··· 1722 1714 1723 1715 mapping_set_error(inode->i_mapping, error); 1724 1716 spin_lock(&fi->lock); 1717 + rb_erase(&wpa->writepages_entry, &fi->writepages); 1725 1718 while (wpa->next) { 1726 1719 struct fuse_conn *fc = get_fuse_conn(inode); 1727 1720 struct fuse_write_in *inarg = &wpa->ia.write.in; ··· 1961 1952 } 1962 1953 1963 1954 /* 1964 - * First recheck under fi->lock if the offending offset is still under 1965 - * writeback. If yes, then iterate auxiliary write requests, to see if there's 1955 + * Check under fi->lock if the page is under writeback, and insert it onto the 1956 + * rb_tree if not. Otherwise iterate auxiliary write requests, to see if there's 1966 1957 * one already added for a page at this offset. If there's none, then insert 1967 1958 * this new request onto the auxiliary list, otherwise reuse the existing one by 1968 - * copying the new page contents over to the old temporary page. 1959 + * swapping the new temp page with the old one. 1969 1960 */ 1970 - static bool fuse_writepage_in_flight(struct fuse_writepage_args *new_wpa, 1971 - struct page *page) 1961 + static bool fuse_writepage_add(struct fuse_writepage_args *new_wpa, 1962 + struct page *page) 1972 1963 { 1973 1964 struct fuse_inode *fi = get_fuse_inode(new_wpa->inode); 1974 1965 struct fuse_writepage_args *tmp; ··· 1976 1967 struct fuse_args_pages *new_ap = &new_wpa->ia.ap; 1977 1968 1978 1969 WARN_ON(new_ap->num_pages != 0); 1970 + new_ap->num_pages = 1; 1979 1971 1980 1972 spin_lock(&fi->lock); 1981 - rb_erase(&new_wpa->writepages_entry, &fi->writepages); 1982 - old_wpa = fuse_find_writeback(fi, page->index, page->index); 1973 + old_wpa = fuse_insert_writeback(&fi->writepages, new_wpa); 1983 1974 if (!old_wpa) { 1984 - tree_insert(&fi->writepages, new_wpa); 1985 1975 spin_unlock(&fi->lock); 1986 - return false; 1976 + return true; 1987 1977 } 1988 1978 1989 - new_ap->num_pages = 1; 1990 1979 for (tmp = old_wpa->next; tmp; tmp = tmp->next) { 1991 1980 pgoff_t curr_index; 1992 1981 ··· 2013 2006 fuse_writepage_free(new_wpa); 2014 2007 } 2015 2008 2016 - return true; 2009 + return false; 2010 + } 2011 + 2012 + static bool fuse_writepage_need_send(struct fuse_conn *fc, struct page *page, 2013 + struct fuse_args_pages *ap, 2014 + struct fuse_fill_wb_data *data) 2015 + { 2016 + WARN_ON(!ap->num_pages); 2017 + 2018 + /* 2019 + * Being under writeback is unlikely but possible. For example direct 2020 + * read to an mmaped fuse file will set the page dirty twice; once when 2021 + * the pages are faulted with get_user_pages(), and then after the read 2022 + * completed. 2023 + */ 2024 + if (fuse_page_is_writeback(data->inode, page->index)) 2025 + return true; 2026 + 2027 + /* Reached max pages */ 2028 + if (ap->num_pages == fc->max_pages) 2029 + return true; 2030 + 2031 + /* Reached max write bytes */ 2032 + if ((ap->num_pages + 1) * PAGE_SIZE > fc->max_write) 2033 + return true; 2034 + 2035 + /* Discontinuity */ 2036 + if (data->orig_pages[ap->num_pages - 1]->index + 1 != page->index) 2037 + return true; 2038 + 2039 + /* Need to grow the pages array? If so, did the expansion fail? */ 2040 + if (ap->num_pages == data->max_pages && !fuse_pages_realloc(data)) 2041 + return true; 2042 + 2043 + return false; 2017 2044 } 2018 2045 2019 2046 static int fuse_writepages_fill(struct page *page, ··· 2060 2019 struct fuse_inode *fi = get_fuse_inode(inode); 2061 2020 struct fuse_conn *fc = get_fuse_conn(inode); 2062 2021 struct page *tmp_page; 2063 - bool is_writeback; 2064 2022 int err; 2065 2023 2066 2024 if (!data->ff) { ··· 2069 2029 goto out_unlock; 2070 2030 } 2071 2031 2072 - /* 2073 - * Being under writeback is unlikely but possible. For example direct 2074 - * read to an mmaped fuse file will set the page dirty twice; once when 2075 - * the pages are faulted with get_user_pages(), and then after the read 2076 - * completed. 2077 - */ 2078 - is_writeback = fuse_page_is_writeback(inode, page->index); 2079 - 2080 - if (wpa && ap->num_pages && 2081 - (is_writeback || ap->num_pages == fc->max_pages || 2082 - (ap->num_pages + 1) * PAGE_SIZE > fc->max_write || 2083 - data->orig_pages[ap->num_pages - 1]->index + 1 != page->index)) { 2032 + if (wpa && fuse_writepage_need_send(fc, page, ap, data)) { 2084 2033 fuse_writepages_send(data); 2085 2034 data->wpa = NULL; 2086 - } else if (wpa && ap->num_pages == data->max_pages) { 2087 - if (!fuse_pages_realloc(data)) { 2088 - fuse_writepages_send(data); 2089 - data->wpa = NULL; 2090 - } 2091 2035 } 2092 2036 2093 2037 err = -ENOMEM; ··· 2109 2085 ap->args.end = fuse_writepage_end; 2110 2086 ap->num_pages = 0; 2111 2087 wpa->inode = inode; 2112 - 2113 - spin_lock(&fi->lock); 2114 - tree_insert(&fi->writepages, wpa); 2115 - spin_unlock(&fi->lock); 2116 - 2117 - data->wpa = wpa; 2118 2088 } 2119 2089 set_page_writeback(page); 2120 2090 ··· 2116 2098 ap->pages[ap->num_pages] = tmp_page; 2117 2099 ap->descs[ap->num_pages].offset = 0; 2118 2100 ap->descs[ap->num_pages].length = PAGE_SIZE; 2101 + data->orig_pages[ap->num_pages] = page; 2119 2102 2120 2103 inc_wb_stat(&inode_to_bdi(inode)->wb, WB_WRITEBACK); 2121 2104 inc_node_page_state(tmp_page, NR_WRITEBACK_TEMP); 2122 2105 2123 2106 err = 0; 2124 - if (is_writeback && fuse_writepage_in_flight(wpa, page)) { 2107 + if (data->wpa) { 2108 + /* 2109 + * Protected by fi->lock against concurrent access by 2110 + * fuse_page_is_writeback(). 2111 + */ 2112 + spin_lock(&fi->lock); 2113 + ap->num_pages++; 2114 + spin_unlock(&fi->lock); 2115 + } else if (fuse_writepage_add(wpa, page)) { 2116 + data->wpa = wpa; 2117 + } else { 2125 2118 end_page_writeback(page); 2126 - data->wpa = NULL; 2127 - goto out_unlock; 2128 2119 } 2129 - data->orig_pages[ap->num_pages] = page; 2130 - 2131 - /* 2132 - * Protected by fi->lock against concurrent access by 2133 - * fuse_page_is_writeback(). 2134 - */ 2135 - spin_lock(&fi->lock); 2136 - ap->num_pages++; 2137 - spin_unlock(&fi->lock); 2138 - 2139 2120 out_unlock: 2140 2121 unlock_page(page); 2141 2122 ··· 2166 2149 2167 2150 err = write_cache_pages(mapping, wbc, fuse_writepages_fill, &data); 2168 2151 if (data.wpa) { 2169 - /* Ignore errors if we can write at least one page */ 2170 2152 WARN_ON(!data.wpa->ia.ap.num_pages); 2171 2153 fuse_writepages_send(&data); 2172 - err = 0; 2173 2154 } 2174 2155 if (data.ff) 2175 2156 fuse_file_put(data.ff, false, false); ··· 2776 2761 struct iovec *iov = iov_page; 2777 2762 2778 2763 iov->iov_base = (void __user *)arg; 2779 - iov->iov_len = _IOC_SIZE(cmd); 2764 + 2765 + switch (cmd) { 2766 + case FS_IOC_GETFLAGS: 2767 + case FS_IOC_SETFLAGS: 2768 + iov->iov_len = sizeof(int); 2769 + break; 2770 + default: 2771 + iov->iov_len = _IOC_SIZE(cmd); 2772 + break; 2773 + } 2780 2774 2781 2775 if (_IOC_DIR(cmd) & _IOC_WRITE) { 2782 2776 in_iov = iov;
+16 -3
fs/fuse/inode.c
··· 121 121 } 122 122 } 123 123 124 - static int fuse_remount_fs(struct super_block *sb, int *flags, char *data) 124 + static int fuse_reconfigure(struct fs_context *fc) 125 125 { 126 + struct super_block *sb = fc->root->d_sb; 127 + 126 128 sync_filesystem(sb); 127 - if (*flags & SB_MANDLOCK) 129 + if (fc->sb_flags & SB_MANDLOCK) 128 130 return -EINVAL; 129 131 130 132 return 0; ··· 477 475 struct fuse_fs_context *ctx = fc->fs_private; 478 476 int opt; 479 477 478 + if (fc->purpose == FS_CONTEXT_FOR_RECONFIGURE) { 479 + /* 480 + * Ignore options coming from mount(MS_REMOUNT) for backward 481 + * compatibility. 482 + */ 483 + if (fc->oldapi) 484 + return 0; 485 + 486 + return invalfc(fc, "No changes allowed in reconfigure"); 487 + } 488 + 480 489 opt = fs_parse(fc, fuse_fs_parameters, param, &result); 481 490 if (opt < 0) 482 491 return opt; ··· 830 817 .evict_inode = fuse_evict_inode, 831 818 .write_inode = fuse_write_inode, 832 819 .drop_inode = generic_delete_inode, 833 - .remount_fs = fuse_remount_fs, 834 820 .put_super = fuse_put_super, 835 821 .umount_begin = fuse_umount_begin, 836 822 .statfs = fuse_statfs, ··· 1308 1296 static const struct fs_context_operations fuse_context_ops = { 1309 1297 .free = fuse_free_fc, 1310 1298 .parse_param = fuse_parse_param, 1299 + .reconfigure = fuse_reconfigure, 1311 1300 .get_tree = fuse_get_tree, 1312 1301 }; 1313 1302
+1
fs/namespace.c
··· 2603 2603 if (IS_ERR(fc)) 2604 2604 return PTR_ERR(fc); 2605 2605 2606 + fc->oldapi = true; 2606 2607 err = parse_monolithic_mount_data(fc, data); 2607 2608 if (!err) { 2608 2609 down_write(&sb->s_umount);
+1
include/linux/fs_context.h
··· 109 109 enum fs_context_phase phase:8; /* The phase the context is in */ 110 110 bool need_free:1; /* Need to call ops->free() */ 111 111 bool global:1; /* Goes into &init_user_ns */ 112 + bool oldapi:1; /* Coming from mount(2) */ 112 113 }; 113 114 114 115 struct fs_context_operations {