]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/commitdiff
4.9-stable patches
authorGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Mon, 12 Jun 2017 09:19:48 +0000 (11:19 +0200)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Mon, 12 Jun 2017 09:19:48 +0000 (11:19 +0200)
added patches:
btrfs-fix-memory-leak-in-update_space_info-failure-path.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
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

12 files changed:
queue-4.9/btrfs-fix-memory-leak-in-update_space_info-failure-path.patch [new file with mode: 0644]
queue-4.9/btrfs-use-correct-types-for-page-indices-in-btrfs_page_exists_in_range.patch [new file with mode: 0644]
queue-4.9/cpuset-consider-dying-css-as-offline.patch [new file with mode: 0644]
queue-4.9/cxl-avoid-double-free_irq-for-psl-slice-interrupts.patch [new file with mode: 0644]
queue-4.9/cxl-fix-error-path-on-bad-ioctl.patch [new file with mode: 0644]
queue-4.9/fix-ufs_isblockset.patch [new file with mode: 0644]
queue-4.9/series
queue-4.9/ufs-restore-maintaining-i_blocks.patch [new file with mode: 0644]
queue-4.9/ufs-restore-proper-tail-allocation.patch [new file with mode: 0644]
queue-4.9/ufs-set-correct-s_maxsize.patch [new file with mode: 0644]
queue-4.9/ufs_extend_tail-fix-the-braino-in-calling-conventions-of-ufs_new_fragments.patch [new file with mode: 0644]
queue-4.9/ufs_getfrag_block-we-only-grab-truncate_mutex-on-block-creation-path.patch [new file with mode: 0644]

diff --git a/queue-4.9/btrfs-fix-memory-leak-in-update_space_info-failure-path.patch b/queue-4.9/btrfs-fix-memory-leak-in-update_space_info-failure-path.patch
new file mode 100644 (file)
index 0000000..85216a2
--- /dev/null
@@ -0,0 +1,32 @@
+From 896533a7da929136d0432713f02a3edffece2826 Mon Sep 17 00:00:00 2001
+From: Jeff Mahoney <jeffm@suse.com>
+Date: Wed, 17 May 2017 09:49:37 -0400
+Subject: btrfs: fix memory leak in update_space_info failure path
+
+From: Jeff Mahoney <jeffm@suse.com>
+
+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 <jeffm@suse.com>
+Reviewed-by: Liu Bo <bo.li.liu@oracle.com>
+Signed-off-by: David Sterba <dsterba@suse.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ fs/btrfs/extent-tree.c |    1 +
+ 1 file changed, 1 insertion(+)
+
+--- a/fs/btrfs/extent-tree.c
++++ b/fs/btrfs/extent-tree.c
+@@ -3984,6 +3984,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.9/btrfs-use-correct-types-for-page-indices-in-btrfs_page_exists_in_range.patch b/queue-4.9/btrfs-use-correct-types-for-page-indices-in-btrfs_page_exists_in_range.patch
new file mode 100644 (file)
index 0000000..f7170ec
--- /dev/null
@@ -0,0 +1,64 @@
+From cc2b702c52094b637a351d7491ac5200331d0445 Mon Sep 17 00:00:00 2001
+From: David Sterba <dsterba@suse.com>
+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 <dsterba@suse.com>
+
+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 <bo.li.liu@oracle.com>
+Fixes: fc4adbff823f7 ("btrfs: Drop EXTENT_UPTODATE check in hole punching and direct locking")
+Reviewed-by: Liu Bo <bo.li.liu@oracle.com>
+Signed-off-by: David Sterba <dsterba@suse.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ fs/btrfs/inode.c |    4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+--- a/fs/btrfs/inode.c
++++ b/fs/btrfs/inode.c
+@@ -7435,8 +7435,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.9/cpuset-consider-dying-css-as-offline.patch b/queue-4.9/cpuset-consider-dying-css-as-offline.patch
new file mode 100644 (file)
index 0000000..feb119d
--- /dev/null
@@ -0,0 +1,79 @@
+From 41c25707d21716826e3c1f60967f5550610ec1c9 Mon Sep 17 00:00:00 2001
+From: Tejun Heo <tj@kernel.org>
+Date: Wed, 24 May 2017 12:03:48 -0400
+Subject: cpuset: consider dying css as offline
+
+From: Tejun Heo <tj@kernel.org>
+
+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 <tj@kernel.org>
+Reported-by: Daniel Jordan <daniel.m.jordan@oracle.com>
+Link: http://lkml.kernel.org/r/327ca1f5-7957-fbb9-9e5f-9ba149d40ba2@oracle.com
+Signed-off-by: Tejun Heo <tj@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ include/linux/cgroup.h |   20 ++++++++++++++++++++
+ kernel/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/cpuset.c
++++ b/kernel/cpuset.c
+@@ -174,9 +174,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.9/cxl-avoid-double-free_irq-for-psl-slice-interrupts.patch b/queue-4.9/cxl-avoid-double-free_irq-for-psl-slice-interrupts.patch
new file mode 100644 (file)
index 0000000..ea4207c
--- /dev/null
@@ -0,0 +1,100 @@
+From b3aa20ba2ba8072b73bd799605b8c98927b7056c Mon Sep 17 00:00:00 2001
+From: Vaibhav Jain <vaibhav@linux.vnet.ibm.com>
+Date: Fri, 2 Jun 2017 22:26:48 +0530
+Subject: cxl: Avoid double free_irq() for psl,slice interrupts
+
+From: Vaibhav Jain <vaibhav@linux.vnet.ibm.com>
+
+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 <vaibhav@linux.vnet.ibm.com>
+Reviewed-by: Andrew Donnellan <andrew.donnellan@au1.ibm.com>
+Acked-by: Frederic Barrat <fbarrat@linux.vnet.ibm.com>
+Signed-off-by: Michael Ellerman <mpe@ellerman.id.au>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ 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
+@@ -1066,13 +1066,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)
+@@ -1102,13 +1105,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)
+@@ -1131,12 +1136,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.9/cxl-fix-error-path-on-bad-ioctl.patch b/queue-4.9/cxl-fix-error-path-on-bad-ioctl.patch
new file mode 100644 (file)
index 0000000..986b011
--- /dev/null
@@ -0,0 +1,40 @@
+From cec422c11caeeccae709e9942058b6b644ce434c Mon Sep 17 00:00:00 2001
+From: Frederic Barrat <fbarrat@linux.vnet.ibm.com>
+Date: Tue, 6 Jun 2017 11:43:41 +0200
+Subject: cxl: Fix error path on bad ioctl
+
+From: Frederic Barrat <fbarrat@linux.vnet.ibm.com>
+
+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 <fbarrat@linux.vnet.ibm.com>
+Reviewed-by: Vaibhav Jain <vaibhav@linux.vnet.ibm.com>
+Reviewed-by: Andrew Donnellan <andrew.donnellan@au1.ibm.com>
+Signed-off-by: Michael Ellerman <mpe@ellerman.id.au>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ 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
+@@ -155,11 +155,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.9/fix-ufs_isblockset.patch b/queue-4.9/fix-ufs_isblockset.patch
new file mode 100644 (file)
index 0000000..19e8f6e
--- /dev/null
@@ -0,0 +1,41 @@
+From 414cf7186dbec29bd946c138d6b5c09da5955a08 Mon Sep 17 00:00:00 2001
+From: Al Viro <viro@zeniv.linux.org.uk>
+Date: Thu, 8 Jun 2017 18:15:18 -0400
+Subject: fix ufs_isblockset()
+
+From: Al Viro <viro@zeniv.linux.org.uk>
+
+commit 414cf7186dbec29bd946c138d6b5c09da5955a08 upstream.
+
+Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ 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;       
+ }
index 6aa1dd5e299a1b8dafa232965a4ca84919e4c7fd..edda98703a8ebb60168986c8018a404eb2620ddc 100644 (file)
@@ -72,3 +72,14 @@ drm-msm-expose-our-reservation-object-when-exporting-a-dmabuf.patch
 ahci-acer-sa5-271-ssd-not-detected-fix.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
+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
diff --git a/queue-4.9/ufs-restore-maintaining-i_blocks.patch b/queue-4.9/ufs-restore-maintaining-i_blocks.patch
new file mode 100644 (file)
index 0000000..0f138b9
--- /dev/null
@@ -0,0 +1,104 @@
+From eb315d2ae614493fd1ebb026c75a80573d84f7ad Mon Sep 17 00:00:00 2001
+From: Al Viro <viro@zeniv.linux.org.uk>
+Date: Thu, 8 Jun 2017 21:15:03 -0400
+Subject: ufs: restore maintaining ->i_blocks
+
+From: Al Viro <viro@zeniv.linux.org.uk>
+
+commit eb315d2ae614493fd1ebb026c75a80573d84f7ad upstream.
+
+Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ fs/stat.c       |    1 +
+ fs/ufs/balloc.c |   26 +++++++++++++++++++++++++-
+ 2 files changed, 26 insertions(+), 1 deletion(-)
+
+--- a/fs/stat.c
++++ b/fs/stat.c
+@@ -454,6 +454,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
+@@ -81,7 +81,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);
+@@ -183,6 +184,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.9/ufs-restore-proper-tail-allocation.patch b/queue-4.9/ufs-restore-proper-tail-allocation.patch
new file mode 100644 (file)
index 0000000..c857c9d
--- /dev/null
@@ -0,0 +1,27 @@
+From 8785d84d002c2ce0f68fbcd6c2c86be859802c7e Mon Sep 17 00:00:00 2001
+From: Al Viro <viro@zeniv.linux.org.uk>
+Date: Thu, 8 Jun 2017 02:42:03 -0400
+Subject: ufs: restore proper tail allocation
+
+From: Al Viro <viro@zeniv.linux.org.uk>
+
+commit 8785d84d002c2ce0f68fbcd6c2c86be859802c7e upstream.
+
+Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ 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.9/ufs-set-correct-s_maxsize.patch b/queue-4.9/ufs-set-correct-s_maxsize.patch
new file mode 100644 (file)
index 0000000..9537be4
--- /dev/null
@@ -0,0 +1,50 @@
+From 6b0d144fa758869bdd652c50aa41aaf601232550 Mon Sep 17 00:00:00 2001
+From: Al Viro <viro@zeniv.linux.org.uk>
+Date: Thu, 8 Jun 2017 21:15:45 -0400
+Subject: ufs: set correct ->s_maxsize
+
+From: Al Viro <viro@zeniv.linux.org.uk>
+
+commit 6b0d144fa758869bdd652c50aa41aaf601232550 upstream.
+
+Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ 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.9/ufs_extend_tail-fix-the-braino-in-calling-conventions-of-ufs_new_fragments.patch b/queue-4.9/ufs_extend_tail-fix-the-braino-in-calling-conventions-of-ufs_new_fragments.patch
new file mode 100644 (file)
index 0000000..8f9c1ea
--- /dev/null
@@ -0,0 +1,31 @@
+From 940ef1a0ed939c2ca029fca715e25e7778ce1e34 Mon Sep 17 00:00:00 2001
+From: Al Viro <viro@zeniv.linux.org.uk>
+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 <viro@zeniv.linux.org.uk>
+
+commit 940ef1a0ed939c2ca029fca715e25e7778ce1e34 upstream.
+
+... and it really needs splitting into "new" and "extend" cases, but that's for
+later
+
+Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ 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.9/ufs_getfrag_block-we-only-grab-truncate_mutex-on-block-creation-path.patch b/queue-4.9/ufs_getfrag_block-we-only-grab-truncate_mutex-on-block-creation-path.patch
new file mode 100644 (file)
index 0000000..0926fb5
--- /dev/null
@@ -0,0 +1,29 @@
+From 006351ac8ead0d4a67dd3845e3ceffe650a23212 Mon Sep 17 00:00:00 2001
+From: Al Viro <viro@zeniv.linux.org.uk>
+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 <viro@zeniv.linux.org.uk>
+
+commit 006351ac8ead0d4a67dd3845e3ceffe650a23212 upstream.
+
+Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ 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 ....? */