From: Greg Kroah-Hartman Date: Mon, 12 Jun 2017 09:18:56 +0000 (+0200) Subject: 4.11-stable patches X-Git-Tag: v3.18.57~21 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=4e1308c704046197d90e7196592228f31f1282ed;p=thirdparty%2Fkernel%2Fstable-queue.git 4.11-stable patches added patches: btrfs-fix-delalloc-accounting-leak-caused-by-u32-overflow.patch btrfs-fix-memory-leak-in-update_space_info-failure-path.patch btrfs-fix-race-with-relocation-recovery-and-fs_root-setup.patch btrfs-use-correct-types-for-page-indices-in-btrfs_page_exists_in_range.patch cpuset-consider-dying-css-as-offline.patch cxl-avoid-double-free_irq-for-psl-slice-interrupts.patch cxl-fix-error-path-on-bad-ioctl.patch excessive-checks-in-ufs_write_failed-and-ufs_evict_inode.patch fix-ufs_isblockset.patch ufs-restore-maintaining-i_blocks.patch ufs-restore-proper-tail-allocation.patch ufs-set-correct-s_maxsize.patch ufs_extend_tail-fix-the-braino-in-calling-conventions-of-ufs_new_fragments.patch ufs_getfrag_block-we-only-grab-truncate_mutex-on-block-creation-path.patch --- diff --git a/queue-4.11/btrfs-fix-delalloc-accounting-leak-caused-by-u32-overflow.patch b/queue-4.11/btrfs-fix-delalloc-accounting-leak-caused-by-u32-overflow.patch new file mode 100644 index 00000000000..17f676a5044 --- /dev/null +++ b/queue-4.11/btrfs-fix-delalloc-accounting-leak-caused-by-u32-overflow.patch @@ -0,0 +1,69 @@ +From 70e7af244f24c94604ef6eca32ad297632018583 Mon Sep 17 00:00:00 2001 +From: Omar Sandoval +Date: Fri, 2 Jun 2017 01:20:01 -0700 +Subject: Btrfs: fix delalloc accounting leak caused by u32 overflow + +From: Omar Sandoval + +commit 70e7af244f24c94604ef6eca32ad297632018583 upstream. + +btrfs_calc_trans_metadata_size() does an unsigned 32-bit multiplication, +which can overflow if num_items >= 4 GB / (nodesize * BTRFS_MAX_LEVEL * 2). +For a nodesize of 16kB, this overflow happens at 16k items. Usually, +num_items is a small constant passed to btrfs_start_transaction(), but +we also use btrfs_calc_trans_metadata_size() for metadata reservations +for extent items in btrfs_delalloc_{reserve,release}_metadata(). + +In drop_outstanding_extents(), num_items is calculated as +inode->reserved_extents - inode->outstanding_extents. The difference +between these two counters is usually small, but if many delalloc +extents are reserved and then the outstanding extents are merged in +btrfs_merge_extent_hook(), the difference can become large enough to +overflow in btrfs_calc_trans_metadata_size(). + +The overflow manifests itself as a leak of a multiple of 4 GB in +delalloc_block_rsv and the metadata bytes_may_use counter. This in turn +can cause early ENOSPC errors. Additionally, these WARN_ONs in +extent-tree.c will be hit when unmounting: + + WARN_ON(fs_info->delalloc_block_rsv.size > 0); + WARN_ON(fs_info->delalloc_block_rsv.reserved > 0); + WARN_ON(space_info->bytes_pinned > 0 || + space_info->bytes_reserved > 0 || + space_info->bytes_may_use > 0); + +Fix it by casting nodesize to a u64 so that +btrfs_calc_trans_metadata_size() does a full 64-bit multiplication. +While we're here, do the same in btrfs_calc_trunc_metadata_size(); this +can't overflow with any existing uses, but it's better to be safe here +than have another hard-to-debug problem later on. + +Signed-off-by: Omar Sandoval +Reviewed-by: David Sterba +Signed-off-by: Chris Mason +Signed-off-by: Greg Kroah-Hartman + +--- + fs/btrfs/ctree.h | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +--- a/fs/btrfs/ctree.h ++++ b/fs/btrfs/ctree.h +@@ -2547,7 +2547,7 @@ u64 btrfs_csum_bytes_to_leaves(struct bt + static inline u64 btrfs_calc_trans_metadata_size(struct btrfs_fs_info *fs_info, + unsigned num_items) + { +- return fs_info->nodesize * BTRFS_MAX_LEVEL * 2 * num_items; ++ return (u64)fs_info->nodesize * BTRFS_MAX_LEVEL * 2 * num_items; + } + + /* +@@ -2557,7 +2557,7 @@ static inline u64 btrfs_calc_trans_metad + static inline u64 btrfs_calc_trunc_metadata_size(struct btrfs_fs_info *fs_info, + unsigned num_items) + { +- return fs_info->nodesize * BTRFS_MAX_LEVEL * num_items; ++ return (u64)fs_info->nodesize * BTRFS_MAX_LEVEL * num_items; + } + + int btrfs_should_throttle_delayed_refs(struct btrfs_trans_handle *trans, diff --git a/queue-4.11/btrfs-fix-memory-leak-in-update_space_info-failure-path.patch b/queue-4.11/btrfs-fix-memory-leak-in-update_space_info-failure-path.patch new file mode 100644 index 00000000000..5675d083b17 --- /dev/null +++ b/queue-4.11/btrfs-fix-memory-leak-in-update_space_info-failure-path.patch @@ -0,0 +1,32 @@ +From 896533a7da929136d0432713f02a3edffece2826 Mon Sep 17 00:00:00 2001 +From: Jeff Mahoney +Date: Wed, 17 May 2017 09:49:37 -0400 +Subject: btrfs: fix memory leak in update_space_info failure path + +From: Jeff Mahoney + +commit 896533a7da929136d0432713f02a3edffece2826 upstream. + +If we fail to add the space_info kobject, we'll leak the memory +for the percpu counter. + +Fixes: 6ab0a2029c (btrfs: publish allocation data in sysfs) +Signed-off-by: Jeff Mahoney +Reviewed-by: Liu Bo +Signed-off-by: David Sterba +Signed-off-by: Greg Kroah-Hartman + +--- + fs/btrfs/extent-tree.c | 1 + + 1 file changed, 1 insertion(+) + +--- a/fs/btrfs/extent-tree.c ++++ b/fs/btrfs/extent-tree.c +@@ -3983,6 +3983,7 @@ static int update_space_info(struct btrf + info->space_info_kobj, "%s", + alloc_name(found->flags)); + if (ret) { ++ percpu_counter_destroy(&found->total_bytes_pinned); + kfree(found); + return ret; + } diff --git a/queue-4.11/btrfs-fix-race-with-relocation-recovery-and-fs_root-setup.patch b/queue-4.11/btrfs-fix-race-with-relocation-recovery-and-fs_root-setup.patch new file mode 100644 index 00000000000..ca6e1c5feba --- /dev/null +++ b/queue-4.11/btrfs-fix-race-with-relocation-recovery-and-fs_root-setup.patch @@ -0,0 +1,69 @@ +From a9b3311ef36b670909ea4443f306c8318082c8f0 Mon Sep 17 00:00:00 2001 +From: Jeff Mahoney +Date: Wed, 17 May 2017 11:38:34 -0400 +Subject: btrfs: fix race with relocation recovery and fs_root setup + +From: Jeff Mahoney + +commit a9b3311ef36b670909ea4443f306c8318082c8f0 upstream. + +If we have to recover relocation during mount, we'll ultimately have to +evict the orphan inode. That goes through the reservation dance, where +priority_reclaim_metadata_space and flush_space expect fs_info->fs_root +to be valid. That's the next thing to be set up during mount, so we +crash, almost always in flush_space trying to join the transaction +but priority_reclaim_metadata_space is possible as well. This call +path has been problematic in the past WRT whether ->fs_root is valid +yet. Commit 957780eb278 (Btrfs: introduce ticketed enospc +infrastructure) added new users that are called in the direct path +instead of the async path that had already been worked around. + +The thing is that we don't actually need the fs_root, specifically, for +anything. We either use it to determine whether the root is the +chunk_root for use in choosing an allocation profile or as a root to pass +btrfs_join_transaction before immediately committing it. Anything that +isn't the chunk root works in the former case and any root works in +the latter. + +A simple fix is to use a root we know will always be there: the +extent_root. + +Fixes: 957780eb278 (Btrfs: introduce ticketed enospc infrastructure) +Signed-off-by: Jeff Mahoney +Reviewed-by: Liu Bo +Signed-off-by: David Sterba +Signed-off-by: Greg Kroah-Hartman + +--- + fs/btrfs/extent-tree.c | 6 +++--- + 1 file changed, 3 insertions(+), 3 deletions(-) + +--- a/fs/btrfs/extent-tree.c ++++ b/fs/btrfs/extent-tree.c +@@ -4835,7 +4835,7 @@ static int may_commit_transaction(struct + spin_unlock(&delayed_rsv->lock); + + commit: +- trans = btrfs_join_transaction(fs_info->fs_root); ++ trans = btrfs_join_transaction(fs_info->extent_root); + if (IS_ERR(trans)) + return -ENOSPC; + +@@ -4853,7 +4853,7 @@ static int flush_space(struct btrfs_fs_i + struct btrfs_space_info *space_info, u64 num_bytes, + u64 orig_bytes, int state) + { +- struct btrfs_root *root = fs_info->fs_root; ++ struct btrfs_root *root = fs_info->extent_root; + struct btrfs_trans_handle *trans; + int nr; + int ret = 0; +@@ -5053,7 +5053,7 @@ static void priority_reclaim_metadata_sp + int flush_state = FLUSH_DELAYED_ITEMS_NR; + + spin_lock(&space_info->lock); +- to_reclaim = btrfs_calc_reclaim_metadata_size(fs_info->fs_root, ++ to_reclaim = btrfs_calc_reclaim_metadata_size(fs_info->extent_root, + space_info); + if (!to_reclaim) { + spin_unlock(&space_info->lock); diff --git a/queue-4.11/btrfs-use-correct-types-for-page-indices-in-btrfs_page_exists_in_range.patch b/queue-4.11/btrfs-use-correct-types-for-page-indices-in-btrfs_page_exists_in_range.patch new file mode 100644 index 00000000000..3475dc3fb1c --- /dev/null +++ b/queue-4.11/btrfs-use-correct-types-for-page-indices-in-btrfs_page_exists_in_range.patch @@ -0,0 +1,64 @@ +From cc2b702c52094b637a351d7491ac5200331d0445 Mon Sep 17 00:00:00 2001 +From: David Sterba +Date: Fri, 12 May 2017 01:03:52 +0200 +Subject: btrfs: use correct types for page indices in btrfs_page_exists_in_range + +From: David Sterba + +commit cc2b702c52094b637a351d7491ac5200331d0445 upstream. + +Variables start_idx and end_idx are supposed to hold a page index +derived from the file offsets. The int type is not the right one though, +offsets larger than 1 << 44 will get silently trimmed off the high bits. +(1 << 44 is 16TiB) + +What can go wrong, if start is below the boundary and end gets trimmed: +- if there's a page after start, we'll find it (radix_tree_gang_lookup_slot) +- the final check "if (page->index <= end_idx)" will unexpectedly fail + +The function will return false, ie. "there's no page in the range", +although there is at least one. + +btrfs_page_exists_in_range is used to prevent races in: + +* in hole punching, where we make sure there are not pages in the + truncated range, otherwise we'll wait for them to finish and redo + truncation, but we're going to replace the pages with holes anyway so + the only problem is the intermediate state + +* lock_extent_direct: we want to make sure there are no pages before we + lock and start DIO, to prevent stale data reads + +For practical occurence of the bug, there are several constaints. The +file must be quite large, the affected range must cross the 16TiB +boundary and the internal state of the file pages and pending operations +must match. Also, we must not have started any ordered data in the +range, otherwise we don't even reach the buggy function check. + +DIO locking tries hard in several places to avoid deadlocks with +buffered IO and avoids waiting for ranges. The worst consequence seems +to be stale data read. + +CC: Liu Bo +Fixes: fc4adbff823f7 ("btrfs: Drop EXTENT_UPTODATE check in hole punching and direct locking") +Reviewed-by: Liu Bo +Signed-off-by: David Sterba +Signed-off-by: Greg Kroah-Hartman + +--- + fs/btrfs/inode.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +--- a/fs/btrfs/inode.c ++++ b/fs/btrfs/inode.c +@@ -7359,8 +7359,8 @@ bool btrfs_page_exists_in_range(struct i + int found = false; + void **pagep = NULL; + struct page *page = NULL; +- int start_idx; +- int end_idx; ++ unsigned long start_idx; ++ unsigned long end_idx; + + start_idx = start >> PAGE_SHIFT; + diff --git a/queue-4.11/cpuset-consider-dying-css-as-offline.patch b/queue-4.11/cpuset-consider-dying-css-as-offline.patch new file mode 100644 index 00000000000..aa9b8b424c4 --- /dev/null +++ b/queue-4.11/cpuset-consider-dying-css-as-offline.patch @@ -0,0 +1,79 @@ +From 41c25707d21716826e3c1f60967f5550610ec1c9 Mon Sep 17 00:00:00 2001 +From: Tejun Heo +Date: Wed, 24 May 2017 12:03:48 -0400 +Subject: cpuset: consider dying css as offline + +From: Tejun Heo + +commit 41c25707d21716826e3c1f60967f5550610ec1c9 upstream. + +In most cases, a cgroup controller don't care about the liftimes of +cgroups. For the controller, a css becomes online when ->css_online() +is called on it and offline when ->css_offline() is called. + +However, cpuset is special in that the user interface it exposes cares +whether certain cgroups exist or not. Combined with the RCU delay +between cgroup removal and css offlining, this can lead to user +visible behavior oddities where operations which should succeed after +cgroup removals fail for some time period. The effects of cgroup +removals are delayed when seen from userland. + +This patch adds css_is_dying() which tests whether offline is pending +and updates is_cpuset_online() so that the function returns false also +while offline is pending. This gets rid of the userland visible +delays. + +Signed-off-by: Tejun Heo +Reported-by: Daniel Jordan +Link: http://lkml.kernel.org/r/327ca1f5-7957-fbb9-9e5f-9ba149d40ba2@oracle.com +Signed-off-by: Tejun Heo +Signed-off-by: Greg Kroah-Hartman + +--- + include/linux/cgroup.h | 20 ++++++++++++++++++++ + kernel/cgroup/cpuset.c | 4 ++-- + 2 files changed, 22 insertions(+), 2 deletions(-) + +--- a/include/linux/cgroup.h ++++ b/include/linux/cgroup.h +@@ -344,6 +344,26 @@ static inline bool css_tryget_online(str + } + + /** ++ * css_is_dying - test whether the specified css is dying ++ * @css: target css ++ * ++ * Test whether @css is in the process of offlining or already offline. In ++ * most cases, ->css_online() and ->css_offline() callbacks should be ++ * enough; however, the actual offline operations are RCU delayed and this ++ * test returns %true also when @css is scheduled to be offlined. ++ * ++ * This is useful, for example, when the use case requires synchronous ++ * behavior with respect to cgroup removal. cgroup removal schedules css ++ * offlining but the css can seem alive while the operation is being ++ * delayed. If the delay affects user visible semantics, this test can be ++ * used to resolve the situation. ++ */ ++static inline bool css_is_dying(struct cgroup_subsys_state *css) ++{ ++ return !(css->flags & CSS_NO_REF) && percpu_ref_is_dying(&css->refcnt); ++} ++ ++/** + * css_put - put a css reference + * @css: target css + * +--- a/kernel/cgroup/cpuset.c ++++ b/kernel/cgroup/cpuset.c +@@ -176,9 +176,9 @@ typedef enum { + } cpuset_flagbits_t; + + /* convenient tests for these bits */ +-static inline bool is_cpuset_online(const struct cpuset *cs) ++static inline bool is_cpuset_online(struct cpuset *cs) + { +- return test_bit(CS_ONLINE, &cs->flags); ++ return test_bit(CS_ONLINE, &cs->flags) && !css_is_dying(&cs->css); + } + + static inline int is_cpu_exclusive(const struct cpuset *cs) diff --git a/queue-4.11/cxl-avoid-double-free_irq-for-psl-slice-interrupts.patch b/queue-4.11/cxl-avoid-double-free_irq-for-psl-slice-interrupts.patch new file mode 100644 index 00000000000..0a796864c48 --- /dev/null +++ b/queue-4.11/cxl-avoid-double-free_irq-for-psl-slice-interrupts.patch @@ -0,0 +1,100 @@ +From b3aa20ba2ba8072b73bd799605b8c98927b7056c Mon Sep 17 00:00:00 2001 +From: Vaibhav Jain +Date: Fri, 2 Jun 2017 22:26:48 +0530 +Subject: cxl: Avoid double free_irq() for psl,slice interrupts + +From: Vaibhav Jain + +commit b3aa20ba2ba8072b73bd799605b8c98927b7056c upstream. + +During an eeh call to cxl_remove can result in double free_irq of +psl,slice interrupts. This can happen if perst_reloads_same_image == 1 +and call to cxl_configure_adapter() fails during slot_reset +callback. In such a case we see a kernel oops with following back-trace: + +Oops: Kernel access of bad area, sig: 11 [#1] +Call Trace: + free_irq+0x88/0xd0 (unreliable) + cxl_unmap_irq+0x20/0x40 [cxl] + cxl_native_release_psl_irq+0x78/0xd8 [cxl] + pci_deconfigure_afu+0xac/0x110 [cxl] + cxl_remove+0x104/0x210 [cxl] + pci_device_remove+0x6c/0x110 + device_release_driver_internal+0x204/0x2e0 + pci_stop_bus_device+0xa0/0xd0 + pci_stop_and_remove_bus_device+0x28/0x40 + pci_hp_remove_devices+0xb0/0x150 + pci_hp_remove_devices+0x68/0x150 + eeh_handle_normal_event+0x140/0x580 + eeh_handle_event+0x174/0x360 + eeh_event_handler+0x1e8/0x1f0 + +This patch fixes the issue of double free_irq by checking that +variables that hold the virqs (err_hwirq, serr_hwirq, psl_virq) are +not '0' before un-mapping and resetting these variables to '0' when +they are un-mapped. + +Signed-off-by: Vaibhav Jain +Reviewed-by: Andrew Donnellan +Acked-by: Frederic Barrat +Signed-off-by: Michael Ellerman +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/misc/cxl/native.c | 14 +++++++++++--- + 1 file changed, 11 insertions(+), 3 deletions(-) + +--- a/drivers/misc/cxl/native.c ++++ b/drivers/misc/cxl/native.c +@@ -1075,13 +1075,16 @@ int cxl_native_register_psl_err_irq(stru + + void cxl_native_release_psl_err_irq(struct cxl *adapter) + { +- if (adapter->native->err_virq != irq_find_mapping(NULL, adapter->native->err_hwirq)) ++ if (adapter->native->err_virq == 0 || ++ adapter->native->err_virq != ++ irq_find_mapping(NULL, adapter->native->err_hwirq)) + return; + + cxl_p1_write(adapter, CXL_PSL_ErrIVTE, 0x0000000000000000); + cxl_unmap_irq(adapter->native->err_virq, adapter); + cxl_ops->release_one_irq(adapter, adapter->native->err_hwirq); + kfree(adapter->irq_name); ++ adapter->native->err_virq = 0; + } + + int cxl_native_register_serr_irq(struct cxl_afu *afu) +@@ -1111,13 +1114,15 @@ int cxl_native_register_serr_irq(struct + + void cxl_native_release_serr_irq(struct cxl_afu *afu) + { +- if (afu->serr_virq != irq_find_mapping(NULL, afu->serr_hwirq)) ++ if (afu->serr_virq == 0 || ++ afu->serr_virq != irq_find_mapping(NULL, afu->serr_hwirq)) + return; + + cxl_p1n_write(afu, CXL_PSL_SERR_An, 0x0000000000000000); + cxl_unmap_irq(afu->serr_virq, afu); + cxl_ops->release_one_irq(afu->adapter, afu->serr_hwirq); + kfree(afu->err_irq_name); ++ afu->serr_virq = 0; + } + + int cxl_native_register_psl_irq(struct cxl_afu *afu) +@@ -1140,12 +1145,15 @@ int cxl_native_register_psl_irq(struct c + + void cxl_native_release_psl_irq(struct cxl_afu *afu) + { +- if (afu->native->psl_virq != irq_find_mapping(NULL, afu->native->psl_hwirq)) ++ if (afu->native->psl_virq == 0 || ++ afu->native->psl_virq != ++ irq_find_mapping(NULL, afu->native->psl_hwirq)) + return; + + cxl_unmap_irq(afu->native->psl_virq, afu); + cxl_ops->release_one_irq(afu->adapter, afu->native->psl_hwirq); + kfree(afu->psl_irq_name); ++ afu->native->psl_virq = 0; + } + + static void recover_psl_err(struct cxl_afu *afu, u64 errstat) diff --git a/queue-4.11/cxl-fix-error-path-on-bad-ioctl.patch b/queue-4.11/cxl-fix-error-path-on-bad-ioctl.patch new file mode 100644 index 00000000000..0e9e95d7032 --- /dev/null +++ b/queue-4.11/cxl-fix-error-path-on-bad-ioctl.patch @@ -0,0 +1,40 @@ +From cec422c11caeeccae709e9942058b6b644ce434c Mon Sep 17 00:00:00 2001 +From: Frederic Barrat +Date: Tue, 6 Jun 2017 11:43:41 +0200 +Subject: cxl: Fix error path on bad ioctl + +From: Frederic Barrat + +commit cec422c11caeeccae709e9942058b6b644ce434c upstream. + +Fix error path if we can't copy user structure on CXL_IOCTL_START_WORK +ioctl. We shouldn't unlock the context status mutex as it was not +locked (yet). + +Fixes: 0712dc7e73e5 ("cxl: Fix issues when unmapping contexts") +Signed-off-by: Frederic Barrat +Reviewed-by: Vaibhav Jain +Reviewed-by: Andrew Donnellan +Signed-off-by: Michael Ellerman +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/misc/cxl/file.c | 7 ++----- + 1 file changed, 2 insertions(+), 5 deletions(-) + +--- a/drivers/misc/cxl/file.c ++++ b/drivers/misc/cxl/file.c +@@ -158,11 +158,8 @@ static long afu_ioctl_start_work(struct + + /* Do this outside the status_mutex to avoid a circular dependency with + * the locking in cxl_mmap_fault() */ +- if (copy_from_user(&work, uwork, +- sizeof(struct cxl_ioctl_start_work))) { +- rc = -EFAULT; +- goto out; +- } ++ if (copy_from_user(&work, uwork, sizeof(work))) ++ return -EFAULT; + + mutex_lock(&ctx->status_mutex); + if (ctx->status != OPENED) { diff --git a/queue-4.11/excessive-checks-in-ufs_write_failed-and-ufs_evict_inode.patch b/queue-4.11/excessive-checks-in-ufs_write_failed-and-ufs_evict_inode.patch new file mode 100644 index 00000000000..aaece9d334d --- /dev/null +++ b/queue-4.11/excessive-checks-in-ufs_write_failed-and-ufs_evict_inode.patch @@ -0,0 +1,70 @@ +From babef37dccbaa49249a22bae9150686815d7be71 Mon Sep 17 00:00:00 2001 +From: Al Viro +Date: Fri, 9 Jun 2017 16:20:34 -0400 +Subject: excessive checks in ufs_write_failed() and ufs_evict_inode() + +From: Al Viro + +commit babef37dccbaa49249a22bae9150686815d7be71 upstream. + +As it is, short copy in write() to append-only file will fail +to truncate the excessive allocated blocks. As the matter of +fact, all checks in ufs_truncate_blocks() are either redundant +or wrong for that caller. As for the only other caller +(ufs_evict_inode()), we only need the file type checks there. + +Signed-off-by: Al Viro +Signed-off-by: Greg Kroah-Hartman + +--- + fs/ufs/inode.c | 18 +++++------------- + 1 file changed, 5 insertions(+), 13 deletions(-) + +--- a/fs/ufs/inode.c ++++ b/fs/ufs/inode.c +@@ -844,7 +844,9 @@ void ufs_evict_inode(struct inode * inod + truncate_inode_pages_final(&inode->i_data); + if (want_delete) { + inode->i_size = 0; +- if (inode->i_blocks) ++ if (inode->i_blocks && ++ (S_ISREG(inode->i_mode) || S_ISDIR(inode->i_mode) || ++ S_ISLNK(inode->i_mode))) + ufs_truncate_blocks(inode); + } + +@@ -1103,7 +1105,7 @@ out: + return err; + } + +-static void __ufs_truncate_blocks(struct inode *inode) ++static void ufs_truncate_blocks(struct inode *inode) + { + struct ufs_inode_info *ufsi = UFS_I(inode); + struct super_block *sb = inode->i_sb; +@@ -1186,7 +1188,7 @@ static int ufs_truncate(struct inode *in + + truncate_setsize(inode, size); + +- __ufs_truncate_blocks(inode); ++ ufs_truncate_blocks(inode); + inode->i_mtime = inode->i_ctime = current_time(inode); + mark_inode_dirty(inode); + out: +@@ -1194,16 +1196,6 @@ out: + return err; + } + +-static void ufs_truncate_blocks(struct inode *inode) +-{ +- if (!(S_ISREG(inode->i_mode) || S_ISDIR(inode->i_mode) || +- S_ISLNK(inode->i_mode))) +- return; +- if (IS_APPEND(inode) || IS_IMMUTABLE(inode)) +- return; +- __ufs_truncate_blocks(inode); +-} +- + int ufs_setattr(struct dentry *dentry, struct iattr *attr) + { + struct inode *inode = d_inode(dentry); diff --git a/queue-4.11/fix-ufs_isblockset.patch b/queue-4.11/fix-ufs_isblockset.patch new file mode 100644 index 00000000000..19e8f6e3b08 --- /dev/null +++ b/queue-4.11/fix-ufs_isblockset.patch @@ -0,0 +1,41 @@ +From 414cf7186dbec29bd946c138d6b5c09da5955a08 Mon Sep 17 00:00:00 2001 +From: Al Viro +Date: Thu, 8 Jun 2017 18:15:18 -0400 +Subject: fix ufs_isblockset() + +From: Al Viro + +commit 414cf7186dbec29bd946c138d6b5c09da5955a08 upstream. + +Signed-off-by: Al Viro +Signed-off-by: Greg Kroah-Hartman + +--- + fs/ufs/util.h | 10 +++++++--- + 1 file changed, 7 insertions(+), 3 deletions(-) + +--- a/fs/ufs/util.h ++++ b/fs/ufs/util.h +@@ -473,15 +473,19 @@ static inline unsigned _ubh_find_last_ze + static inline int _ubh_isblockset_(struct ufs_sb_private_info * uspi, + struct ufs_buffer_head * ubh, unsigned begin, unsigned block) + { ++ u8 mask; + switch (uspi->s_fpb) { + case 8: + return (*ubh_get_addr (ubh, begin + block) == 0xff); + case 4: +- return (*ubh_get_addr (ubh, begin + (block >> 1)) == (0x0f << ((block & 0x01) << 2))); ++ mask = 0x0f << ((block & 0x01) << 2); ++ return (*ubh_get_addr (ubh, begin + (block >> 1)) & mask) == mask; + case 2: +- return (*ubh_get_addr (ubh, begin + (block >> 2)) == (0x03 << ((block & 0x03) << 1))); ++ mask = 0x03 << ((block & 0x03) << 1); ++ return (*ubh_get_addr (ubh, begin + (block >> 2)) & mask) == mask; + case 1: +- return (*ubh_get_addr (ubh, begin + (block >> 3)) == (0x01 << (block & 0x07))); ++ mask = 0x01 << (block & 0x07); ++ return (*ubh_get_addr (ubh, begin + (block >> 3)) & mask) == mask; + } + return 0; + } diff --git a/queue-4.11/series b/queue-4.11/series index 8f08fc9b0e3..fff82425cff 100644 --- a/queue-4.11/series +++ b/queue-4.11/series @@ -95,3 +95,17 @@ ahci-acer-sa5-271-ssd-not-detected-fix.patch rc-core-race-condition-during-ir_raw_event_register.patch cgroup-prevent-kill_css-from-being-called-more-than-once.patch input-elantech-add-fujitsu-lifebook-e546-e557-to-force-crc_enabled.patch +cpuset-consider-dying-css-as-offline.patch +ufs-restore-proper-tail-allocation.patch +fix-ufs_isblockset.patch +ufs-restore-maintaining-i_blocks.patch +ufs-set-correct-s_maxsize.patch +ufs_extend_tail-fix-the-braino-in-calling-conventions-of-ufs_new_fragments.patch +ufs_getfrag_block-we-only-grab-truncate_mutex-on-block-creation-path.patch +excessive-checks-in-ufs_write_failed-and-ufs_evict_inode.patch +cxl-fix-error-path-on-bad-ioctl.patch +cxl-avoid-double-free_irq-for-psl-slice-interrupts.patch +btrfs-use-correct-types-for-page-indices-in-btrfs_page_exists_in_range.patch +btrfs-fix-memory-leak-in-update_space_info-failure-path.patch +btrfs-fix-race-with-relocation-recovery-and-fs_root-setup.patch +btrfs-fix-delalloc-accounting-leak-caused-by-u32-overflow.patch diff --git a/queue-4.11/ufs-restore-maintaining-i_blocks.patch b/queue-4.11/ufs-restore-maintaining-i_blocks.patch new file mode 100644 index 00000000000..4d2959386f2 --- /dev/null +++ b/queue-4.11/ufs-restore-maintaining-i_blocks.patch @@ -0,0 +1,104 @@ +From eb315d2ae614493fd1ebb026c75a80573d84f7ad Mon Sep 17 00:00:00 2001 +From: Al Viro +Date: Thu, 8 Jun 2017 21:15:03 -0400 +Subject: ufs: restore maintaining ->i_blocks + +From: Al Viro + +commit eb315d2ae614493fd1ebb026c75a80573d84f7ad upstream. + +Signed-off-by: Al Viro +Signed-off-by: Greg Kroah-Hartman + +--- + fs/stat.c | 1 + + fs/ufs/balloc.c | 26 +++++++++++++++++++++++++- + 2 files changed, 26 insertions(+), 1 deletion(-) + +--- a/fs/stat.c ++++ b/fs/stat.c +@@ -586,6 +586,7 @@ void __inode_add_bytes(struct inode *ino + inode->i_bytes -= 512; + } + } ++EXPORT_SYMBOL(__inode_add_bytes); + + void inode_add_bytes(struct inode *inode, loff_t bytes) + { +--- a/fs/ufs/balloc.c ++++ b/fs/ufs/balloc.c +@@ -82,7 +82,8 @@ void ufs_free_fragments(struct inode *in + ufs_error (sb, "ufs_free_fragments", + "bit already cleared for fragment %u", i); + } +- ++ ++ inode_sub_bytes(inode, count << uspi->s_fshift); + fs32_add(sb, &ucg->cg_cs.cs_nffree, count); + uspi->cs_total.cs_nffree += count; + fs32_add(sb, &UFS_SB(sb)->fs_cs(cgno).cs_nffree, count); +@@ -184,6 +185,7 @@ do_more: + ufs_error(sb, "ufs_free_blocks", "freeing free fragment"); + } + ubh_setblock(UCPI_UBH(ucpi), ucpi->c_freeoff, blkno); ++ inode_sub_bytes(inode, uspi->s_fpb << uspi->s_fshift); + if ((UFS_SB(sb)->s_flags & UFS_CG_MASK) == UFS_CG_44BSD) + ufs_clusteracct (sb, ucpi, blkno, 1); + +@@ -494,6 +496,20 @@ u64 ufs_new_fragments(struct inode *inod + return 0; + } + ++static bool try_add_frags(struct inode *inode, unsigned frags) ++{ ++ unsigned size = frags * i_blocksize(inode); ++ spin_lock(&inode->i_lock); ++ __inode_add_bytes(inode, size); ++ if (unlikely((u32)inode->i_blocks != inode->i_blocks)) { ++ __inode_sub_bytes(inode, size); ++ spin_unlock(&inode->i_lock); ++ return false; ++ } ++ spin_unlock(&inode->i_lock); ++ return true; ++} ++ + static u64 ufs_add_fragments(struct inode *inode, u64 fragment, + unsigned oldcount, unsigned newcount) + { +@@ -530,6 +546,9 @@ static u64 ufs_add_fragments(struct inod + for (i = oldcount; i < newcount; i++) + if (ubh_isclr (UCPI_UBH(ucpi), ucpi->c_freeoff, fragno + i)) + return 0; ++ ++ if (!try_add_frags(inode, count)) ++ return 0; + /* + * Block can be extended + */ +@@ -647,6 +666,7 @@ cg_found: + ubh_setbit (UCPI_UBH(ucpi), ucpi->c_freeoff, goal + i); + i = uspi->s_fpb - count; + ++ inode_sub_bytes(inode, i << uspi->s_fshift); + fs32_add(sb, &ucg->cg_cs.cs_nffree, i); + uspi->cs_total.cs_nffree += i; + fs32_add(sb, &UFS_SB(sb)->fs_cs(cgno).cs_nffree, i); +@@ -657,6 +677,8 @@ cg_found: + result = ufs_bitmap_search (sb, ucpi, goal, allocsize); + if (result == INVBLOCK) + return 0; ++ if (!try_add_frags(inode, count)) ++ return 0; + for (i = 0; i < count; i++) + ubh_clrbit (UCPI_UBH(ucpi), ucpi->c_freeoff, result + i); + +@@ -716,6 +738,8 @@ norot: + return INVBLOCK; + ucpi->c_rotor = result; + gotit: ++ if (!try_add_frags(inode, uspi->s_fpb)) ++ return 0; + blkno = ufs_fragstoblks(result); + ubh_clrblock (UCPI_UBH(ucpi), ucpi->c_freeoff, blkno); + if ((UFS_SB(sb)->s_flags & UFS_CG_MASK) == UFS_CG_44BSD) diff --git a/queue-4.11/ufs-restore-proper-tail-allocation.patch b/queue-4.11/ufs-restore-proper-tail-allocation.patch new file mode 100644 index 00000000000..c857c9d5cd4 --- /dev/null +++ b/queue-4.11/ufs-restore-proper-tail-allocation.patch @@ -0,0 +1,27 @@ +From 8785d84d002c2ce0f68fbcd6c2c86be859802c7e Mon Sep 17 00:00:00 2001 +From: Al Viro +Date: Thu, 8 Jun 2017 02:42:03 -0400 +Subject: ufs: restore proper tail allocation + +From: Al Viro + +commit 8785d84d002c2ce0f68fbcd6c2c86be859802c7e upstream. + +Signed-off-by: Al Viro +Signed-off-by: Greg Kroah-Hartman + +--- + fs/ufs/inode.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/fs/ufs/inode.c ++++ b/fs/ufs/inode.c +@@ -284,7 +284,7 @@ ufs_inode_getfrag(struct inode *inode, u + goal += uspi->s_fpb; + } + tmp = ufs_new_fragments(inode, p, ufs_blknum(new_fragment), +- goal, uspi->s_fpb, err, locked_page); ++ goal, nfrags, err, locked_page); + + if (!tmp) { + *err = -ENOSPC; diff --git a/queue-4.11/ufs-set-correct-s_maxsize.patch b/queue-4.11/ufs-set-correct-s_maxsize.patch new file mode 100644 index 00000000000..9537be42b46 --- /dev/null +++ b/queue-4.11/ufs-set-correct-s_maxsize.patch @@ -0,0 +1,50 @@ +From 6b0d144fa758869bdd652c50aa41aaf601232550 Mon Sep 17 00:00:00 2001 +From: Al Viro +Date: Thu, 8 Jun 2017 21:15:45 -0400 +Subject: ufs: set correct ->s_maxsize + +From: Al Viro + +commit 6b0d144fa758869bdd652c50aa41aaf601232550 upstream. + +Signed-off-by: Al Viro +Signed-off-by: Greg Kroah-Hartman + +--- + fs/ufs/super.c | 18 ++++++++++++++++++ + 1 file changed, 18 insertions(+) + +--- a/fs/ufs/super.c ++++ b/fs/ufs/super.c +@@ -746,6 +746,23 @@ static void ufs_put_super(struct super_b + return; + } + ++static u64 ufs_max_bytes(struct super_block *sb) ++{ ++ struct ufs_sb_private_info *uspi = UFS_SB(sb)->s_uspi; ++ int bits = uspi->s_apbshift; ++ u64 res; ++ ++ if (bits > 21) ++ res = ~0ULL; ++ else ++ res = UFS_NDADDR + (1LL << bits) + (1LL << (2*bits)) + ++ (1LL << (3*bits)); ++ ++ if (res >= (MAX_LFS_FILESIZE >> uspi->s_bshift)) ++ return MAX_LFS_FILESIZE; ++ return res << uspi->s_bshift; ++} ++ + static int ufs_fill_super(struct super_block *sb, void *data, int silent) + { + struct ufs_sb_info * sbi; +@@ -1211,6 +1228,7 @@ magic_found: + "fast symlink size (%u)\n", uspi->s_maxsymlinklen); + uspi->s_maxsymlinklen = maxsymlen; + } ++ sb->s_maxbytes = ufs_max_bytes(sb); + sb->s_max_links = UFS_LINK_MAX; + + inode = ufs_iget(sb, UFS_ROOTINO); diff --git a/queue-4.11/ufs_extend_tail-fix-the-braino-in-calling-conventions-of-ufs_new_fragments.patch b/queue-4.11/ufs_extend_tail-fix-the-braino-in-calling-conventions-of-ufs_new_fragments.patch new file mode 100644 index 00000000000..8f9c1ead761 --- /dev/null +++ b/queue-4.11/ufs_extend_tail-fix-the-braino-in-calling-conventions-of-ufs_new_fragments.patch @@ -0,0 +1,31 @@ +From 940ef1a0ed939c2ca029fca715e25e7778ce1e34 Mon Sep 17 00:00:00 2001 +From: Al Viro +Date: Thu, 8 Jun 2017 23:27:12 -0400 +Subject: ufs_extend_tail(): fix the braino in calling conventions of ufs_new_fragments() + +From: Al Viro + +commit 940ef1a0ed939c2ca029fca715e25e7778ce1e34 upstream. + +... and it really needs splitting into "new" and "extend" cases, but that's for +later + +Signed-off-by: Al Viro +Signed-off-by: Greg Kroah-Hartman + +--- + fs/ufs/inode.c | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +--- a/fs/ufs/inode.c ++++ b/fs/ufs/inode.c +@@ -235,7 +235,8 @@ ufs_extend_tail(struct inode *inode, u64 + + p = ufs_get_direct_data_ptr(uspi, ufsi, block); + tmp = ufs_new_fragments(inode, p, lastfrag, ufs_data_ptr_to_cpu(sb, p), +- new_size, err, locked_page); ++ new_size - (lastfrag & uspi->s_fpbmask), err, ++ locked_page); + return tmp != 0; + } + diff --git a/queue-4.11/ufs_getfrag_block-we-only-grab-truncate_mutex-on-block-creation-path.patch b/queue-4.11/ufs_getfrag_block-we-only-grab-truncate_mutex-on-block-creation-path.patch new file mode 100644 index 00000000000..0926fb5f5e3 --- /dev/null +++ b/queue-4.11/ufs_getfrag_block-we-only-grab-truncate_mutex-on-block-creation-path.patch @@ -0,0 +1,29 @@ +From 006351ac8ead0d4a67dd3845e3ceffe650a23212 Mon Sep 17 00:00:00 2001 +From: Al Viro +Date: Thu, 8 Jun 2017 23:28:53 -0400 +Subject: ufs_getfrag_block(): we only grab ->truncate_mutex on block creation path + +From: Al Viro + +commit 006351ac8ead0d4a67dd3845e3ceffe650a23212 upstream. + +Signed-off-by: Al Viro +Signed-off-by: Greg Kroah-Hartman + +--- + fs/ufs/inode.c | 4 +++- + 1 file changed, 3 insertions(+), 1 deletion(-) + +--- a/fs/ufs/inode.c ++++ b/fs/ufs/inode.c +@@ -403,7 +403,9 @@ static int ufs_getfrag_block(struct inod + + if (!create) { + phys64 = ufs_frag_map(inode, offsets, depth); +- goto out; ++ if (phys64) ++ map_bh(bh_result, sb, phys64 + frag); ++ return 0; + } + + /* This code entered only while writing ....? */