Home Home > GIT Browse > openSUSE-42.3
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorOlaf Hering <ohering@suse.de>2018-11-06 18:14:33 +0100
committerOlaf Hering <ohering@suse.de>2018-11-06 18:19:57 +0100
commit7f004c36416b50cb24a27e2fd6160716598f7007 (patch)
treeccfd3277422fe9a6a7d87e9a979605a2bec0cdd7
parentca04a08c67dbb8f700cdd1f362a829db907001bc (diff)
parent18a42b9333544319fe912723c50e23572f32f3e8 (diff)
Merge remote-tracking branch 'kerncvs/SLE12-SP3' into SLE12-SP3-AZURErpm-4.4.162-4.19
-rw-r--r--README24
-rw-r--r--blacklist.conf8
-rw-r--r--patches.drivers/0019-x86-mm-introduce-vmem_altmap-to-augment-vmemmap_populate.patch39
-rw-r--r--patches.drivers/ethtool-Add-phy-statistics.patch3
-rw-r--r--patches.drivers/ib_srp-Remove-WARN_ON-in-srp_terminate_io.patch20
-rw-r--r--patches.drivers/tpm-Restore-functionality-to-xen-vtpm-driver.patch63
-rw-r--r--patches.fixes/0001-btrfs-Enhance-btrfs_trim_fs-function-to-handle-error.patch146
-rw-r--r--patches.fixes/0001-btrfs-Take-trans-lock-before-access-running-trans-in.patch69
-rw-r--r--patches.fixes/0001-btrfs-defrag-use-btrfs_mod_outstanding_extents-in-cl.patch34
-rw-r--r--patches.fixes/0001-cgroup-netclassid-add-a-preemption-point-to-write_cl.patch67
-rw-r--r--patches.fixes/0001-drm-hisilicon-hibmc-Do-not-carry-error-code-in-HiBMC.patch88
-rw-r--r--patches.fixes/0001-drm-hisilicon-hibmc-Don-t-overwrite-fb-helper-surfac.patch41
-rw-r--r--patches.fixes/0001-drm-virtio-fix-bounds-check-in-virtio_gpu_cmd_get_ca.patch54
-rw-r--r--patches.fixes/0001-fbdev-fix-broken-menu-dependencies.patch113
-rw-r--r--patches.fixes/0001-memory_hotplug-cond_resched-in-__remove_pages.patch59
-rw-r--r--patches.fixes/0002-btrfs-Ensure-btrfs_trim_fs-can-trim-the-whole-filesy.patch97
-rw-r--r--patches.fixes/CIFS-511c54a2f69195b28afb9dd119f03787b1625bb4-adds-a-check-for-sess.patch33
-rw-r--r--patches.fixes/cdrom-fix-improper-type-cast-which-can-leat-to-infor.patch38
-rw-r--r--patches.fixes/cifs-Fix-use-after-free-of-a-mid_q_entry.patch188
-rw-r--r--patches.fixes/cifs-fix-memory-leak-in-SMB2_open-.patch47
-rw-r--r--patches.fixes/edac-thunderx-fix-memory-leak-in-thunderx_l2c_threaded_isr.patch44
-rw-r--r--patches.fixes/fs-aio-fix-the-increment-of-aio-nr-and-counting-agai.patch2
-rw-r--r--patches.fixes/mremap-properly-flush-TLB-before-releasing-the-page.patch104
-rw-r--r--patches.fixes/resource-include-resource-end-in-walk_-interfaces.patch76
-rw-r--r--patches.fixes/smb3-fill-in-statfs-fsid-and-correct-namelen.patch109
-rw-r--r--patches.fixes/x86-kexec-correct-kexec_backup_src_end-off-by-one-error.patch62
-rw-r--r--patches.suse/0001-Btrfs-fix-invalid-attempt-to-free-reserved-space-on-.patch235
-rw-r--r--patches.suse/0001-Btrfs-pass-delayed_refs-directly-to-btrfs_find_delay.patch101
-rw-r--r--patches.suse/0001-btrfs-qgroup-Add-quick-exit-for-non-fs-extents.patch121
-rw-r--r--patches.suse/0001-btrfs-qgroup-Add-trace-point-for-qgroup-reserved-spa.patch251
-rw-r--r--patches.suse/0002-Btrfs-kill-trans-in-run_delalloc_nocow-and-btrfs_cro.patch190
-rw-r--r--patches.suse/0002-btrfs-qgroup-Cleanup-btrfs_qgroup_prepare_account_ex.patch139
-rw-r--r--patches.suse/0007-btrfs-qgroup-Skeleton-to-support-separate-qgroup-res.patch150
-rw-r--r--patches.suse/0008-btrfs-qgroup-Introduce-helpers-to-update-and-access-.patch105
-rw-r--r--patches.suse/0009-btrfs-qgroup-Make-qgroup_reserve-and-its-callers-to-.patch91
-rw-r--r--patches.suse/0010-btrfs-qgroup-Fix-wrong-qgroup-reservation-update-for.patch132
-rw-r--r--patches.suse/0011-btrfs-qgroup-Update-trace-events-to-use-new-separate.patch162
-rw-r--r--patches.suse/0012-btrfs-qgroup-Cleanup-the-remaining-old-reservation-c.patch57
-rw-r--r--patches.suse/0013-btrfs-qgroup-Split-meta-rsv-type-into-meta_prealloc-.patch287
-rw-r--r--patches.suse/0014-btrfs-qgroup-Don-t-use-root-qgroup_meta_rsv-for-qgro.patch124
-rw-r--r--patches.suse/0015-btrfs-qgroup-Introduce-function-to-convert-META_PREA.patch110
-rw-r--r--patches.suse/0016-btrfs-cleanup-extent-locking-sequence.patch81
-rw-r--r--patches.suse/0017-Btrfs-rework-outstanding_extents.patch905
-rw-r--r--patches.suse/0018-btrfs-add-tracepoints-for-outstanding-extents-mods.patch61
-rw-r--r--patches.suse/0019-btrfs-make-the-delalloc-block-rsv-per-inode.patch800
-rw-r--r--patches.suse/0020-btrfs-remove-type-argument-from-comp_tree_refs.patch57
-rw-r--r--patches.suse/0021-btrfs-switch-args-for-comp_-_refs.patch49
-rw-r--r--patches.suse/0022-btrfs-add-a-comp_refs-helper.patch101
-rw-r--r--patches.suse/0023-btrfs-qgroup-Use-separate-meta-reservation-type-for-.patch478
-rw-r--r--patches.suse/0024-btrfs-Fix-wrong-btrfs_delalloc_release_extents-param.patch35
-rw-r--r--patches.suse/0025-btrfs-delayed-inode-Use-new-qgroup-meta-rsv-for-dela.patch100
-rw-r--r--patches.suse/0026-btrfs-qgroup-Use-root-qgroup_meta_rsv_-to-record-qgr.patch161
-rw-r--r--patches.suse/0027-btrfs-qgroup-Update-trace-events-for-metadata-reserv.patch141
-rw-r--r--patches.suse/0028-Revert-btrfs-qgroups-Retry-after-commit-on-getting-E.patch98
-rw-r--r--patches.suse/0029-btrfs-qgroup-Commit-transaction-in-advance-to-reduce.patch166
-rw-r--r--patches.suse/0030-btrfs-qgroup-Use-independent-and-accurate-per-inode-.patch238
-rw-r--r--patches.suse/0031-btrfs-delayed-inode-Remove-wrong-qgroup-meta-reserva.patch86
-rw-r--r--patches.suse/btrfs-8888-add-allow_unsupported-module-parameter.patch29
-rw-r--r--patches.suse/btrfs-add-wrapper-for-counting-BTRFS_MAX_EXTENT_SIZE.patch163
-rw-r--r--patches.suse/btrfs-qgroups-opencode-qgroup_free-helper.patch71
-rw-r--r--patches.suse/hwrng-core-document-the-quality-field.patch61
-rw-r--r--patches.suse/irq_data_get_effective_affinity_mask.patch38
-rw-r--r--patches.suse/msft-hv-1545-PCI-hv-Use-effective-affinity-mask.patch4
-rw-r--r--patches.suse/msft-hv-1766-hv_netvsc-fix-vf-serial-matching-with-pci-slot-info.patch3
-rw-r--r--patches.suse/rpmsg-Correct-support-for-MODULE_DEVICE_TABLE.patch52
-rwxr-xr-xrpm/apply-patches2
-rwxr-xr-xrpm/arch-symbols2
-rwxr-xr-xrpm/check-for-config-changes4
-rwxr-xr-xrpm/check-module-license12
-rw-r--r--rpm/constraints.in18
-rw-r--r--rpm/gitlog-excludes38
-rwxr-xr-xrpm/group-source-files.pl1
-rwxr-xr-xrpm/kabi.pl46
-rw-r--r--rpm/kernel-binary.spec.in61
-rw-r--r--rpm/kernel-module-subpackage1
-rw-r--r--rpm/kernel-obs-build.spec.in19
-rw-r--r--rpm/kernel-source.spec.in3
-rw-r--r--rpm/kernel-spec-macros4
-rw-r--r--rpm/kernel-syms.spec.in1
-rw-r--r--rpm/macros.kernel-source44
-rwxr-xr-xrpm/mkspec94
-rw-r--r--rpm/package-descriptions33
-rw-r--r--rpm/release-projects18
-rwxr-xr-xrpm/split-modules4
-rw-r--r--series.conf77
85 files changed, 8209 insertions, 134 deletions
diff --git a/README b/README
index f252cebc73..d7a29d1739 100644
--- a/README
+++ b/README
@@ -105,13 +105,13 @@ what the patch does, who wrote it, and who inside SUSE/Novell we'll
Patch-mainline: Never, <reason>
- * The patch should include a References: tag that identifies the
+ * The patch should include a References: tag that identifies the
Bugzilla bug number, FATE entry, etc. where the patch is discussed.
Please prefix bugzilla.novell.com bug numbers with bnc# and fate
feature numbers with fate#. Have a look at
http://en.opensuse.org/openSUSE:Packaging_Patches_guidelines#Current_set_of_abbreviations
for a full list of abbreviations.
-
+
* The patch header may (and often, should) include a more extensive
description of what the patch does, why, and how. The idea is to
allow others to quickly identify what each patch is about, and to
@@ -136,21 +136,21 @@ Example patch header:
| From: Peter Leckie <pleckie@sgi.com>
| References: SGI:PV986789 bnc#482148
| Subject: Clean up dquot pincount code
- | Patch-mainline: 2.6.28
- |
+ | Patch-mainline: v2.6.28
+ |
| Clean up dquot pincount code.
- |
+ |
| This is a code cleanup and optimization that removes a per mount point
| spinlock from the quota code and cleans up the code.
- |
+ |
| The patch changes the pincount from being an int protected by a spinlock
| to an atomic_t allowing the pincount to be manipulated without holding
| the spinlock.
- |
+ |
| This cleanup also protects against random wakup's of both the aild and
| xfssyncd by reevaluating the pincount after been woken. Two latter patches
| will address the Spurious wakeups.
- |
+ |
| Signed-off-by: Peter Leckie <pleckie@sgi.com>
| Acked-by: Jan Kara <jack@suse.cz>
@@ -167,7 +167,7 @@ required tags described in the section "Patch Headers", run
to insert an entry for a new patch file to the sorted section of series.conf.
-For more information, please read "scripts/git_sort/README.md".
+For more information, please read "scripts/git_sort/README.md".
Before You Commit -- Things To Check
====================================
@@ -235,10 +235,10 @@ example:
| -------------------------------------------------------------------
| Wed Dec 1 18:29:44 CET 2004 - agruen@suse.de
- |
+ |
| - patches.fixes/serialize-dgram-read.diff: Serialize dgram read
| using semaphore just like stream (#48427).
- |
+ |
There is a simple helper script for creating changelog entries in this
format (/work/src/bin/vc).
@@ -296,7 +296,7 @@ During kernel builds, two things related to the kernel ABI happen:
are added, but all previous symbols are still available: in this
case, all modules will continue to load into the new kernel just
fine.
-
+
If a reference symsets file (/boot/symsets-* in kernel-$FLAVOR
packages) for the particular architecture and flavor is available, we
check which of the symbol sets in the reference file can still be
diff --git a/blacklist.conf b/blacklist.conf
index 0d6d4d8c09..2e1caeb327 100644
--- a/blacklist.conf
+++ b/blacklist.conf
@@ -507,3 +507,11 @@ ad608fbcf166fec809e402d548761768f602702c # kABI
128227e7fe4087b60f1bd31f762e61237eb23790 # bnc#1107060
8d3e2936375bacce6abacbce3917d667e4133409 # Requires 51f7e52dc943 as prerequisite
babcbbc7c4e2fa7fa76417ece7c57083bee971f1 # Only a cleanup and only KASAN related
+6fa504835d6969144b2bd3699684dd447c789ba2 # depends on earlier code restructuring we don's have in 4.4
+f2791e7eadf437633f30faa51b30878cf15650be # we need the fix this reverts in favor of another fix (which we don't have).
+e0d34648b4d77ba715e13739d04e7b0692fe5eaa # we don't ship turbostat
+084f5601c357e4ee59cf0712200d3f5c4710ba40 # just a cleanup
+95a001f22b1c5717eafd500a43832249ddd93662 # comment update
+8c74c4561f05f57fca2957b1d98676a0454df1ca # significant difference; no important fix, high regression potential
+c8124d399224d626728e2ffb95a1d564a7c06968 # significant difference; high regression potential
+d9a515867bdba59ebf196a6ade10faae8e8be36a # significant difference; missing interfaces
diff --git a/patches.drivers/0019-x86-mm-introduce-vmem_altmap-to-augment-vmemmap_populate.patch b/patches.drivers/0019-x86-mm-introduce-vmem_altmap-to-augment-vmemmap_populate.patch
index c317fb43a5..b0b46aa982 100644
--- a/patches.drivers/0019-x86-mm-introduce-vmem_altmap-to-augment-vmemmap_populate.patch
+++ b/patches.drivers/0019-x86-mm-introduce-vmem_altmap-to-augment-vmemmap_populate.patch
@@ -30,11 +30,11 @@ Acked-by: Johannes Thumshirn <jthumshirn@suse.com>
include/linux/memremap.h | 39 ++++++++++++++++++---
include/linux/mm.h | 9 ++++
kernel/memremap.c | 72 +++++++++++++++++++++++++++++++++++++-
- mm/memory_hotplug.c | 66 +++++++++++++++++++++++++----------
+ mm/memory_hotplug.c | 65 ++++++++++++++++++++++++-----------
mm/page_alloc.c | 11 +++++
mm/sparse-vmemmap.c | 76 +++++++++++++++++++++++++++++++++++++++--
mm/sparse.c | 8 ++--
- 10 files changed, 281 insertions(+), 42 deletions(-)
+ 10 files changed, 280 insertions(+), 42 deletions(-)
--- a/arch/x86/mm/init_64.c
+++ b/arch/x86/mm/init_64.c
@@ -46,7 +46,7 @@ Acked-by: Johannes Thumshirn <jthumshirn@suse.com>
#include <linux/nmi.h>
#include <linux/gfp.h>
#include <linux/kcore.h>
-@@ -712,6 +713,12 @@ static void __meminit free_pagetable(str
+@@ -722,6 +723,12 @@ static void __meminit free_pagetable(str
{
unsigned long magic;
unsigned int nr_pages = 1 << order;
@@ -59,7 +59,7 @@ Acked-by: Johannes Thumshirn <jthumshirn@suse.com>
/* bootmem page has reserved flag */
if (PageReserved(page)) {
-@@ -1016,13 +1023,19 @@ int __ref arch_remove_memory(u64 start,
+@@ -1026,13 +1033,19 @@ int __ref arch_remove_memory(u64 start,
{
unsigned long start_pfn = start >> PAGE_SHIFT;
unsigned long nr_pages = size >> PAGE_SHIFT;
@@ -81,7 +81,7 @@ Acked-by: Johannes Thumshirn <jthumshirn@suse.com>
return ret;
}
-@@ -1234,7 +1247,7 @@ static void __meminitdata *p_start, *p_e
+@@ -1244,7 +1257,7 @@ static void __meminitdata *p_start, *p_e
static int __meminitdata node_start;
static int __meminit vmemmap_populate_hugepages(unsigned long start,
@@ -90,7 +90,7 @@ Acked-by: Johannes Thumshirn <jthumshirn@suse.com>
{
unsigned long addr;
unsigned long next;
-@@ -1257,7 +1270,7 @@ static int __meminit vmemmap_populate_hu
+@@ -1267,7 +1280,7 @@ static int __meminit vmemmap_populate_hu
if (pmd_none(*pmd)) {
void *p;
@@ -99,7 +99,7 @@ Acked-by: Johannes Thumshirn <jthumshirn@suse.com>
if (p) {
pte_t entry;
-@@ -1278,7 +1291,8 @@ static int __meminit vmemmap_populate_hu
+@@ -1288,7 +1301,8 @@ static int __meminit vmemmap_populate_hu
addr_end = addr + PMD_SIZE;
p_end = p + PMD_SIZE;
continue;
@@ -109,7 +109,7 @@ Acked-by: Johannes Thumshirn <jthumshirn@suse.com>
} else if (pmd_large(*pmd)) {
vmemmap_verify((pte_t *)pmd, node, addr, next);
continue;
-@@ -1292,11 +1306,16 @@ static int __meminit vmemmap_populate_hu
+@@ -1301,11 +1315,16 @@ static int __meminit vmemmap_populate_hu
int __meminit vmemmap_populate(unsigned long start, unsigned long end, int node)
{
@@ -229,7 +229,7 @@ Acked-by: Johannes Thumshirn <jthumshirn@suse.com>
#endif /* _LINUX_MEMREMAP_H_ */
--- a/include/linux/mm.h
+++ b/include/linux/mm.h
-@@ -2248,7 +2248,14 @@ pud_t *vmemmap_pud_populate(pgd_t *pgd,
+@@ -2250,7 +2250,14 @@ pud_t *vmemmap_pud_populate(pgd_t *pgd,
pmd_t *vmemmap_pmd_populate(pud_t *pud, unsigned long addr, int node);
pte_t *vmemmap_pte_populate(pmd_t *pmd, unsigned long addr, int node);
void *vmemmap_alloc_block(unsigned long size, int node);
@@ -406,7 +406,7 @@ Acked-by: Johannes Thumshirn <jthumshirn@suse.com>
for (i = start_sec; i <= end_sec; i++) {
err = __add_section(nid, section_nr_to_pfn(i), want_memblock);
-@@ -547,7 +562,8 @@ static void __remove_zone(struct zone *z
+@@ -548,7 +563,8 @@ static void __remove_zone(struct zone *z
pgdat_resize_unlock(zone->zone_pgdat, &flags);
}
@@ -416,7 +416,7 @@ Acked-by: Johannes Thumshirn <jthumshirn@suse.com>
{
unsigned long start_pfn;
int scn_nr;
-@@ -564,7 +580,7 @@ static int __remove_section(struct zone
+@@ -565,7 +581,7 @@ static int __remove_section(struct zone
start_pfn = section_nr_to_pfn((unsigned long)scn_nr);
__remove_zone(zone, start_pfn);
@@ -425,7 +425,7 @@ Acked-by: Johannes Thumshirn <jthumshirn@suse.com>
return 0;
}
-@@ -583,9 +599,32 @@ int __remove_pages(struct zone *zone, un
+@@ -584,9 +600,32 @@ int __remove_pages(struct zone *zone, un
unsigned long nr_pages)
{
unsigned long i;
@@ -461,7 +461,7 @@ Acked-by: Johannes Thumshirn <jthumshirn@suse.com>
clear_zone_contiguous(zone);
-@@ -595,23 +634,12 @@ int __remove_pages(struct zone *zone, un
+@@ -596,25 +635,13 @@ int __remove_pages(struct zone *zone, un
BUG_ON(phys_start_pfn & ~PAGE_SECTION_MASK);
BUG_ON(nr_pages % PAGES_PER_SECTION);
@@ -481,8 +481,9 @@ Acked-by: Johannes Thumshirn <jthumshirn@suse.com>
sections_to_remove = nr_pages / PAGES_PER_SECTION;
for (i = 0; i < sections_to_remove; i++) {
unsigned long pfn = phys_start_pfn + i*PAGES_PER_SECTION;
+
+ cond_resched();
- ret = __remove_section(zone, __pfn_to_section(pfn));
-+
+ ret = __remove_section(zone, __pfn_to_section(pfn), map_offset);
+ map_offset = 0;
if (ret)
@@ -498,7 +499,7 @@ Acked-by: Johannes Thumshirn <jthumshirn@suse.com>
#include <linux/stop_machine.h>
#include <linux/sort.h>
#include <linux/pfn.h>
-@@ -4901,8 +4902,9 @@ void __ref build_all_zonelists(pg_data_t
+@@ -4914,8 +4915,9 @@ void __ref build_all_zonelists(pg_data_t
void __meminit memmap_init_zone(unsigned long size, int nid, unsigned long zone,
unsigned long start_pfn, enum memmap_context context)
{
@@ -509,7 +510,7 @@ Acked-by: Johannes Thumshirn <jthumshirn@suse.com>
unsigned long pfn;
struct zone *z;
unsigned long nr_initialised = 0;
-@@ -4913,6 +4915,13 @@ void __meminit memmap_init_zone(unsigned
+@@ -4926,6 +4928,13 @@ void __meminit memmap_init_zone(unsigned
if (highest_memmap_pfn < end_pfn - 1)
highest_memmap_pfn = end_pfn - 1;
@@ -533,7 +534,7 @@ Acked-by: Johannes Thumshirn <jthumshirn@suse.com>
#include <linux/highmem.h>
#include <linux/slab.h>
#include <linux/spinlock.h>
-@@ -70,7 +71,7 @@ void * __meminit vmemmap_alloc_block(uns
+@@ -74,7 +75,7 @@ void * __meminit vmemmap_alloc_block(uns
}
/* need to make sure size is all the same during early stage */
@@ -542,7 +543,7 @@ Acked-by: Johannes Thumshirn <jthumshirn@suse.com>
{
void *ptr;
-@@ -87,6 +88,77 @@ void * __meminit vmemmap_alloc_block_buf
+@@ -91,6 +92,77 @@ void * __meminit vmemmap_alloc_block_buf
return ptr;
}
@@ -620,7 +621,7 @@ Acked-by: Johannes Thumshirn <jthumshirn@suse.com>
void __meminit vmemmap_verify(pte_t *pte, int node,
unsigned long start, unsigned long end)
{
-@@ -103,7 +175,7 @@ pte_t * __meminit vmemmap_pte_populate(p
+@@ -107,7 +179,7 @@ pte_t * __meminit vmemmap_pte_populate(p
pte_t *pte = pte_offset_kernel(pmd, addr);
if (pte_none(*pte)) {
pte_t entry;
diff --git a/patches.drivers/ethtool-Add-phy-statistics.patch b/patches.drivers/ethtool-Add-phy-statistics.patch
index cfaa021225..bf1cdeee3c 100644
--- a/patches.drivers/ethtool-Add-phy-statistics.patch
+++ b/patches.drivers/ethtool-Add-phy-statistics.patch
@@ -175,12 +175,13 @@ Signed-off-by: Mian Yousaf Kaukab <yousaf.kaukab@suse.com>
case ETHTOOL_GTSO:
case ETHTOOL_GPERMADDR:
case ETHTOOL_GUFO:
-@@ -2170,6 +2246,8 @@ int dev_ethtool(struct net *net, struct
+@@ -2170,6 +2246,9 @@ int dev_ethtool(struct net *net, struct
case ETHTOOL_STUNABLE:
rc = ethtool_set_tunable(dev, useraddr);
break;
+ case ETHTOOL_GPHYSTATS:
+ rc = ethtool_get_phy_stats(dev, useraddr);
++ break;
case ETHTOOL_PERQUEUE:
rc = ethtool_set_per_queue(dev, useraddr);
break;
diff --git a/patches.drivers/ib_srp-Remove-WARN_ON-in-srp_terminate_io.patch b/patches.drivers/ib_srp-Remove-WARN_ON-in-srp_terminate_io.patch
index 4ac5a0b42e..1f1dc0e894 100644
--- a/patches.drivers/ib_srp-Remove-WARN_ON-in-srp_terminate_io.patch
+++ b/patches.drivers/ib_srp-Remove-WARN_ON-in-srp_terminate_io.patch
@@ -2,22 +2,25 @@ From: Hannes Reinecke <hare@suse.de>
Date: Fri, 21 Sep 2018 14:09:06 +0200
Subject: [PATCH] ib_srp: Remove WARN_ON in srp_terminate_io()
References: bsc#1094562
-Patch-Mainline: submitted linux-scsi 2018/09/21
+Git-commit: 56e027a604c80b1106786f8426e7cc5dbacb53b2
+Patch-Mainline: v4.20-rc1
The WARN_ON() is pointless as the rport is placed in SDEV_TRANSPORT_OFFLINE
at that time, so no new commands can be submitted via srp_queuecomment().
Signed-off-by: Hannes Reinecke <hare@suse.com>
---
- drivers/infiniband/ulp/srp/ib_srp.c | 7 -------
- 1 file changed, 7 deletions(-)
+ drivers/infiniband/ulp/srp/ib_srp.c | 9 ---------
+ 1 file changed, 9 deletions(-)
-diff --git a/drivers/infiniband/ulp/srp/ib_srp.c b/drivers/infiniband/ulp/srp/ib_srp.c
-index 1615bc61b5a7..7675ad941163 100644
--- a/drivers/infiniband/ulp/srp/ib_srp.c
+++ b/drivers/infiniband/ulp/srp/ib_srp.c
-@@ -1179,13 +1179,6 @@ static void srp_terminate_io(struct srp_rport *rport)
- struct scsi_device *sdev;
+@@ -1167,17 +1167,8 @@ static void srp_terminate_io(struct srp_
+ {
+ struct srp_target_port *target = rport->lld_data;
+ struct srp_rdma_ch *ch;
+- struct Scsi_Host *shost = target->scsi_host;
+- struct scsi_device *sdev;
int i, j;
- /*
@@ -30,6 +33,3 @@ index 1615bc61b5a7..7675ad941163 100644
for (i = 0; i < target->ch_count; i++) {
ch = &target->ch[i];
---
-2.16.4
-
diff --git a/patches.drivers/tpm-Restore-functionality-to-xen-vtpm-driver.patch b/patches.drivers/tpm-Restore-functionality-to-xen-vtpm-driver.patch
new file mode 100644
index 0000000000..17ca3088d0
--- /dev/null
+++ b/patches.drivers/tpm-Restore-functionality-to-xen-vtpm-driver.patch
@@ -0,0 +1,63 @@
+From e487a0f52301293152a6f8c4e217f2a11dd808e3 Mon Sep 17 00:00:00 2001
+From: "Dr. Greg Wettstein" <greg@wind.enjellic.com>
+Date: Mon, 17 Sep 2018 18:53:33 -0400
+Subject: [PATCH] tpm: Restore functionality to xen vtpm driver.
+
+References: bsc#1020645, git-fixes
+Patch-mainline: v4.20-rc1
+Git-commit: e487a0f52301293152a6f8c4e217f2a11dd808e3
+
+Functionality of the xen-tpmfront driver was lost secondary to
+the introduction of xenbus multi-page support in commit ccc9d90a9a8b
+("xenbus_client: Extend interface to support multi-page ring").
+
+In this commit pointer to location of where the shared page address
+is stored was being passed to the xenbus_grant_ring() function rather
+then the address of the shared page itself. This resulted in a situation
+where the driver would attach to the vtpm-stubdom but any attempt
+to send a command to the stub domain would timeout.
+
+A diagnostic finding for this regression is the following error
+message being generated when the xen-tpmfront driver probes for a
+device:
+
+<3>vtpm vtpm-0: tpm_transmit: tpm_send: error -62
+
+<3>vtpm vtpm-0: A TPM error (-62) occurred attempting to determine
+the timeouts
+
+This fix is relevant to all kernels from 4.1 forward which is the
+release in which multi-page xenbus support was introduced.
+
+Daniel De Graaf formulated the fix by code inspection after the
+regression point was located.
+
+Fixes: ccc9d90a9a8b ("xenbus_client: Extend interface to support multi-page ring")
+Signed-off-by: Dr. Greg Wettstein <greg@enjellic.com>
+
+[boris: Updated commit message, added Fixes tag]
+Signed-off-by: Boris Ostrovsky <boris.ostrovsky@oracle.com>
+Cc: stable@vger.kernel.org # v4.1+
+Reviewed-by: Jarkko Sakkinen <jarkko.sakkinen@linux.intel.com>
+Signed-off-by: Jarkko Sakkinen <jarkko.sakkinen@linux.intel.com>
+Acked-by: Michal Suchanek <msuchanek@suse.de>
+---
+ drivers/char/tpm/xen-tpmfront.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/drivers/char/tpm/xen-tpmfront.c b/drivers/char/tpm/xen-tpmfront.c
+index 911475d36800..b150f87f38f5 100644
+--- a/drivers/char/tpm/xen-tpmfront.c
++++ b/drivers/char/tpm/xen-tpmfront.c
+@@ -264,7 +264,7 @@ static int setup_ring(struct xenbus_device *dev, struct tpm_private *priv)
+ return -ENOMEM;
+ }
+
+- rv = xenbus_grant_ring(dev, &priv->shr, 1, &gref);
++ rv = xenbus_grant_ring(dev, priv->shr, 1, &gref);
+ if (rv < 0)
+ return rv;
+
+--
+2.13.7
+
diff --git a/patches.fixes/0001-btrfs-Enhance-btrfs_trim_fs-function-to-handle-error.patch b/patches.fixes/0001-btrfs-Enhance-btrfs_trim_fs-function-to-handle-error.patch
new file mode 100644
index 0000000000..358ca1971d
--- /dev/null
+++ b/patches.fixes/0001-btrfs-Enhance-btrfs_trim_fs-function-to-handle-error.patch
@@ -0,0 +1,146 @@
+From 93bba24d4b5ad1e5cd8b43f64e66ff9d6355dd20 Mon Sep 17 00:00:00 2001
+From: Qu Wenruo <wqu@suse.com>
+Date: Fri, 7 Sep 2018 14:16:23 +0800
+Patch-mainline: v4.20
+Git-commit: 93bba24d4b5ad1e5cd8b43f64e66ff9d6355dd20
+References: Dependency for bsc#1113667
+Subject: [PATCH 1/2] btrfs: Enhance btrfs_trim_fs function to handle error
+ better
+
+Function btrfs_trim_fs() doesn't handle errors in a consistent way. If
+error happens when trimming existing block groups, it will skip the
+remaining blocks and continue to trim unallocated space for each device.
+
+The return value will only reflect the final error from device trimming.
+
+This patch will fix such behavior by:
+
+1) Recording the last error from block group or device trimming
+ The return value will also reflect the last error during trimming.
+ Make developer more aware of the problem.
+
+2) Continuing trimming if possible
+ If we failed to trim one block group or device, we could still try
+ the next block group or device.
+
+3) Report number of failures during block group and device trimming
+ It would be less noisy, but still gives user a brief summary of
+ what's going wrong.
+
+Such behavior can avoid confusion for cases like failure to trim the
+first block group and then only unallocated space is trimmed.
+
+Reported-by: Chris Murphy <lists@colorremedies.com>
+CC: stable@vger.kernel.org # 4.4+
+Signed-off-by: Qu Wenruo <wqu@suse.com>
+Reviewed-by: David Sterba <dsterba@suse.com>
+[ add bg_ret and dev_ret to the messages ]
+Signed-off-by: David Sterba <dsterba@suse.com>
+---
+ fs/btrfs/extent-tree.c | 48 ++++++++++++++++++++++++++++++++++++++----------
+ 1 file changed, 38 insertions(+), 10 deletions(-)
+
+--- a/fs/btrfs/extent-tree.c
++++ b/fs/btrfs/extent-tree.c
+@@ -11018,6 +11018,15 @@ static int btrfs_trim_free_extents(struc
+ return ret;
+ }
+
++/*
++ * Trim the whole filesystem by:
++ * 1) trimming the free space in each block group
++ * 2) trimming the unallocated space on each device
++ *
++ * This will also continue trimming even if a block group or device encounters
++ * an error. The return value will be the last error, or 0 if nothing bad
++ * happens.
++ */
+ int btrfs_trim_fs(struct btrfs_root *root, struct fstrim_range *range)
+ {
+ struct btrfs_fs_info *fs_info = root->fs_info;
+@@ -11029,6 +11038,10 @@ int btrfs_trim_fs(struct btrfs_root *roo
+ u64 end;
+ u64 trimmed = 0;
+ u64 total_bytes = btrfs_super_total_bytes(fs_info->super_copy);
++ u64 bg_failed = 0;
++ u64 dev_failed = 0;
++ int bg_ret = 0;
++ int dev_ret = 0;
+ int ret = 0;
+
+ /*
+@@ -11039,7 +11052,7 @@ int btrfs_trim_fs(struct btrfs_root *roo
+ else
+ cache = btrfs_lookup_block_group(fs_info, range->start);
+
+- while (cache) {
++ for (; cache; cache = next_block_group(root, cache)) {
+ if (cache->key.objectid >= (range->start + range->len)) {
+ btrfs_put_block_group(cache);
+ break;
+@@ -11053,13 +11066,15 @@ int btrfs_trim_fs(struct btrfs_root *roo
+ if (!block_group_cache_done(cache)) {
+ ret = cache_block_group(cache, 0);
+ if (ret) {
+- btrfs_put_block_group(cache);
+- break;
++ bg_failed++;
++ bg_ret = ret;
++ continue;
+ }
+ ret = wait_block_group_cache_done(cache);
+ if (ret) {
+- btrfs_put_block_group(cache);
+- break;
++ bg_failed++;
++ bg_ret = ret;
++ continue;
+ }
+ }
+ ret = btrfs_trim_block_group(cache,
+@@ -11070,27 +11085,40 @@ int btrfs_trim_fs(struct btrfs_root *roo
+
+ trimmed += group_trimmed;
+ if (ret) {
+- btrfs_put_block_group(cache);
+- break;
++ bg_failed++;
++ bg_ret = ret;
++ continue;
+ }
+ }
+-
+- cache = next_block_group(fs_info->tree_root, cache);
+ }
+
++ if (bg_failed)
++ btrfs_warn(fs_info,
++ "failed to trim %llu block group(s), last error %d",
++ bg_failed, bg_ret);
++
+ mutex_lock(&root->fs_info->fs_devices->device_list_mutex);
+ devices = &root->fs_info->fs_devices->alloc_list;
+ list_for_each_entry(device, devices, dev_alloc_list) {
+ ret = btrfs_trim_free_extents(device, range->minlen,
+ &group_trimmed);
+- if (ret)
++ if (ret) {
++ dev_failed++;
++ dev_ret = ret;
+ break;
++ }
+
+ trimmed += group_trimmed;
+ }
+ mutex_unlock(&root->fs_info->fs_devices->device_list_mutex);
+
++ if (dev_failed)
++ btrfs_warn(fs_info,
++ "failed to trim %llu device(s), last error %d",
++ dev_failed, dev_ret);
+ range->len = trimmed;
++ if (bg_ret)
++ return bg_ret;
+ return ret;
+ }
+
diff --git a/patches.fixes/0001-btrfs-Take-trans-lock-before-access-running-trans-in.patch b/patches.fixes/0001-btrfs-Take-trans-lock-before-access-running-trans-in.patch
new file mode 100644
index 0000000000..71fb8e858e
--- /dev/null
+++ b/patches.fixes/0001-btrfs-Take-trans-lock-before-access-running-trans-in.patch
@@ -0,0 +1,69 @@
+From 998ac6d21cfd6efd58f5edf420bae8839dda9f2a Mon Sep 17 00:00:00 2001
+From: ethanwu <ethanwu@synology.com>
+Date: Sun, 29 Apr 2018 15:59:42 +0800
+Patch-mainline: 4.17
+Git-commit: 998ac6d21cfd6efd58f5edf420bae8839dda9f2a
+References: Follow up fixes for bsc#1031392
+Subject: [PATCH] btrfs: Take trans lock before access running trans in
+ check_delayed_ref
+
+In preivous patch:
+Btrfs: kill trans in run_delalloc_nocow and btrfs_cross_ref_exist
+We avoid starting btrfs transaction and get this information from
+fs_info->running_transaction directly.
+
+When accessing running_transaction in check_delayed_ref, there's a
+chance that current transaction will be freed by commit transaction
+after the NULL pointer check of running_transaction is passed.
+
+After looking all the other places using fs_info->running_transaction,
+they are either protected by trans_lock or holding the transactions.
+
+Fix this by using trans_lock and increasing the use_count.
+
+Fixes: e4c3b2dcd144 ("Btrfs: kill trans in run_delalloc_nocow and btrfs_cross_ref_exist")
+CC: stable@vger.kernel.org # 4.14+
+Signed-off-by: ethanwu <ethanwu@synology.com>
+Signed-off-by: David Sterba <dsterba@suse.com>
+---
+ fs/btrfs/extent-tree.c | 7 +++++++
+ 1 file changed, 7 insertions(+)
+
+--- a/fs/btrfs/extent-tree.c
++++ b/fs/btrfs/extent-tree.c
+@@ -3086,7 +3086,11 @@ static noinline int check_delayed_ref(st
+ struct btrfs_transaction *cur_trans;
+ int ret = 0;
+
++ spin_lock(&root->fs_info->trans_lock);
+ cur_trans = root->fs_info->running_transaction;
++ if (cur_trans)
++ atomic_inc(&cur_trans->use_count);
++ spin_unlock(&root->fs_info->trans_lock);
+ if (!cur_trans)
+ return 0;
+
+@@ -3095,6 +3099,7 @@ static noinline int check_delayed_ref(st
+ head = btrfs_find_delayed_ref_head(delayed_refs, bytenr);
+ if (!head) {
+ spin_unlock(&delayed_refs->lock);
++ btrfs_put_transaction(cur_trans);
+ return 0;
+ }
+
+@@ -3111,6 +3116,7 @@ static noinline int check_delayed_ref(st
+ mutex_lock(&head->mutex);
+ mutex_unlock(&head->mutex);
+ btrfs_put_delayed_ref(&head->node);
++ btrfs_put_transaction(cur_trans);
+ return -EAGAIN;
+ }
+ spin_unlock(&delayed_refs->lock);
+@@ -3138,6 +3144,7 @@ static noinline int check_delayed_ref(st
+ }
+ spin_unlock(&head->lock);
+ mutex_unlock(&head->mutex);
++ btrfs_put_transaction(cur_trans);
+ return ret;
+ }
+
diff --git a/patches.fixes/0001-btrfs-defrag-use-btrfs_mod_outstanding_extents-in-cl.patch b/patches.fixes/0001-btrfs-defrag-use-btrfs_mod_outstanding_extents-in-cl.patch
new file mode 100644
index 0000000000..bb77aebc0b
--- /dev/null
+++ b/patches.fixes/0001-btrfs-defrag-use-btrfs_mod_outstanding_extents-in-cl.patch
@@ -0,0 +1,34 @@
+From 28c4a3e21ad030d7571ee9b1b246a5cbfd886627 Mon Sep 17 00:00:00 2001
+From: Su Yue <suy.fnst@cn.fujitsu.com>
+Date: Wed, 5 Sep 2018 11:07:33 +0800
+Patch-mainline: 4.20
+Git-commit: 28c4a3e21ad030d7571ee9b1b246a5cbfd886627
+References: Follow up fixes for bsc#1031392
+Subject: [PATCH] btrfs: defrag: use btrfs_mod_outstanding_extents in
+ cluster_pages_for_defrag
+
+Since commit 8b62f87bad9c ("Btrfs: rework outstanding_extents"),
+manual operations of outstanding_extent in btrfs_inode are replaced by
+btrfs_mod_outstanding_extents().
+The one in cluster_pages_for_defrag seems to be lost, so replace it
+of btrfs_mod_outstanding_extents().
+
+Fixes: 8b62f87bad9c ("Btrfs: rework outstanding_extents")
+Signed-off-by: Su Yue <suy.fnst@cn.fujitsu.com>
+Reviewed-by: David Sterba <dsterba@suse.com>
+Signed-off-by: David Sterba <dsterba@suse.com>
+---
+ fs/btrfs/ioctl.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+--- a/fs/btrfs/ioctl.c
++++ b/fs/btrfs/ioctl.c
+@@ -1231,7 +1231,7 @@ again:
+
+ if (i_done != page_cnt) {
+ spin_lock(&BTRFS_I(inode)->lock);
+- BTRFS_I(inode)->outstanding_extents++;
++ btrfs_mod_outstanding_extents(BTRFS_I(inode), 1);
+ spin_unlock(&BTRFS_I(inode)->lock);
+ btrfs_delalloc_release_space(inode, data_reserved,
+ start_index << PAGE_CACHE_SHIFT,
diff --git a/patches.fixes/0001-cgroup-netclassid-add-a-preemption-point-to-write_cl.patch b/patches.fixes/0001-cgroup-netclassid-add-a-preemption-point-to-write_cl.patch
new file mode 100644
index 0000000000..4396c29713
--- /dev/null
+++ b/patches.fixes/0001-cgroup-netclassid-add-a-preemption-point-to-write_cl.patch
@@ -0,0 +1,67 @@
+From 9d53fadea1c1cbabbbdf3438d6b505638211102e Mon Sep 17 00:00:00 2001
+From: Michal Hocko <mhocko@suse.com>
+Date: Thu, 18 Oct 2018 10:47:03 +0200
+Subject: [PATCH] cgroup, netclassid: add a preemption point to write_classid
+Patch-mainline: 4.20-rc1
+Git-commit: a90e90b7d55e789c71d85b946ffb5c1ab2f137ca
+References: bnc#1098996
+
+We have seen a customer complaining about soft lockups on !PREEMPT
+kernel config with 4.4 based kernel
+
+[1072141.435366] NMI watchdog: BUG: soft lockup - CPU#21 stuck for 22s! [systemd:1]
+[1072141.444090] Modules linked in: mpt3sas raid_class binfmt_misc af_packet 8021q garp mrp stp llc xfs libcrc32c bonding iscsi_ibft iscsi_boot_sysfs msr ext4 crc16 jbd2 mbcache cdc_ether usbnet mii joydev hid_generic usbhid intel_rapl x86_pkg_temp_thermal intel_powerclamp coretemp crct10dif_pclmul crc32_pclmul ghash_clmulni_intel ipmi_ssif mgag200 i2c_algo_bit ttm ipmi_devintf drbg ixgbe drm_kms_helper vxlan ansi_cprng ip6_udp_tunnel drm aesni_intel udp_tunnel aes_x86_64 iTCO_wdt syscopyarea ptp xhci_pci lrw iTCO_vendor_support pps_core gf128mul ehci_pci glue_helper sysfillrect mdio pcspkr sb_edac ablk_helper cryptd ehci_hcd sysimgblt xhci_hcd fb_sys_fops edac_core mei_me lpc_ich ses usbcore enclosure dca mfd_core ipmi_si mei i2c_i801 scsi_transport_sas usb_common ipmi_msghandler shpchp fjes wmi processor button acpi_pad btrfs xor raid6_pq sd_mod crc32c_intel megaraid_sas sg dm_multipath dm_mod scsi_dh_rdac scsi_dh_emc scsi_dh_alua scsi_mod md_mod autofs4
+[1072141.444146] Supported: Yes
+[1072141.444149] CPU: 21 PID: 1 Comm: systemd Not tainted 4.4.121-92.80-default #1
+[1072141.444150] Hardware name: LENOVO Lenovo System x3650 M5 -[5462P4U]- -[5462P4U]-/01GR451, BIOS -[TCE136H-2.70]- 06/13/2018
+[1072141.444151] task: ffff880191bd0040 ti: ffff880191bd4000 task.ti: ffff880191bd4000
+[1072141.444153] RIP: 0010:[<ffffffff815229f9>] [<ffffffff815229f9>] update_classid_sock+0x29/0x40
+[1072141.444157] RSP: 0018:ffff880191bd7d58 EFLAGS: 00000286
+[1072141.444158] RAX: ffff883b177cb7c0 RBX: 0000000000000000 RCX: 0000000000000000
+[1072141.444159] RDX: 00000000000009c7 RSI: ffff880191bd7d5c RDI: ffff8822e29bb200
+[1072141.444160] RBP: ffff883a72230980 R08: 0000000000000101 R09: 0000000000000000
+[1072141.444161] R10: 0000000000000008 R11: f000000000000000 R12: ffffffff815229d0
+[1072141.444162] R13: 0000000000000000 R14: ffff881fd0a47ac0 R15: ffff880191bd7f28
+[1072141.444163] FS: 00007f3e2f1eb8c0(0000) GS:ffff882000340000(0000) knlGS:0000000000000000
+[1072141.444164] CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033
+[1072141.444165] CR2: 00007f3e2f200000 CR3: 0000001ffea4e000 CR4: 00000000001606f0
+[1072141.444166] Stack:
+[1072141.444166] ffffffa800000246 00000000000009c7 ffffffff8121d583 ffff8818312a05c0
+[1072141.444168] ffff8818312a1100 ffff880197c3b280 ffff881861422858 ffffffffffffffea
+[1072141.444170] ffffffff81522b1c ffffffff81d0ca20 ffff8817fa17b950 ffff883fdd8121e0
+[1072141.444171] Call Trace:
+[1072141.444179] [<ffffffff8121d583>] iterate_fd+0x53/0x80
+[1072141.444182] [<ffffffff81522b1c>] write_classid+0x4c/0x80
+[1072141.444187] [<ffffffff8111328b>] cgroup_file_write+0x9b/0x100
+[1072141.444193] [<ffffffff81278bcb>] kernfs_fop_write+0x11b/0x150
+[1072141.444198] [<ffffffff81201566>] __vfs_write+0x26/0x100
+[1072141.444201] [<ffffffff81201bed>] vfs_write+0x9d/0x190
+[1072141.444203] [<ffffffff812028c2>] SyS_write+0x42/0xa0
+[1072141.444207] [<ffffffff815f58c3>] entry_SYSCALL_64_fastpath+0x1e/0xca
+[1072141.445490] DWARF2 unwinder stuck at entry_SYSCALL_64_fastpath+0x1e/0xca
+
+If a cgroup has many tasks with many open file descriptors then we would
+end up in a large loop without any rescheduling point throught the
+operation. Add cond_resched once per task.
+
+Signed-off-by: Michal Hocko <mhocko@suse.com>
+
+---
+ net/core/netclassid_cgroup.c | 1 +
+ 1 file changed, 1 insertion(+)
+
+diff --git a/net/core/netclassid_cgroup.c b/net/core/netclassid_cgroup.c
+index 5e4f04004a49..7bf833598615 100644
+--- a/net/core/netclassid_cgroup.c
++++ b/net/core/netclassid_cgroup.c
+@@ -106,6 +106,7 @@ static int write_classid(struct cgroup_subsys_state *css, struct cftype *cft,
+ iterate_fd(p->files, 0, update_classid_sock,
+ (void *)(unsigned long)cs->classid);
+ task_unlock(p);
++ cond_resched();
+ }
+ css_task_iter_end(&it);
+
+--
+2.19.1
+
diff --git a/patches.fixes/0001-drm-hisilicon-hibmc-Do-not-carry-error-code-in-HiBMC.patch b/patches.fixes/0001-drm-hisilicon-hibmc-Do-not-carry-error-code-in-HiBMC.patch
new file mode 100644
index 0000000000..7e02d84ede
--- /dev/null
+++ b/patches.fixes/0001-drm-hisilicon-hibmc-Do-not-carry-error-code-in-HiBMC.patch
@@ -0,0 +1,88 @@
+From 331d880b35a76b5de0eec8cbcecbf615d758a5f9 Mon Sep 17 00:00:00 2001
+From: John Garry <john.garry@huawei.com>
+Date: Sat, 22 Sep 2018 01:25:25 +0800
+Subject: drm/hisilicon: hibmc: Do not carry error code in HiBMC framebuffer
+ pointer
+Git-commit: 331d880b35a76b5de0eec8cbcecbf615d758a5f9
+Patch-mainline: v4.20-rc1
+References: bsc#1113766
+
+In hibmc_drm_fb_create(), when the call to hibmc_framebuffer_init() fails
+with error, do not store the error code in the HiBMC device frame-buffer
+pointer, as this will be later checked for non-zero value in
+hibmc_fbdev_destroy() when our intention is to check for a valid function
+pointer.
+
+This fixes the following crash:
+[ 9.699791] Unable to handle kernel NULL pointer dereference at virtual address 000000000000001a
+[ 9.708672] Mem abort info:
+[ 9.711489] ESR = 0x96000004
+[ 9.714570] Exception class = DABT (current EL), IL = 32 bits
+[ 9.720551] SET = 0, FnV = 0
+[ 9.723631] EA = 0, S1PTW = 0
+[ 9.726799] Data abort info:
+[ 9.729702] ISV = 0, ISS = 0x00000004
+[ 9.733573] CM = 0, WnR = 0
+[ 9.736566] [000000000000001a] user address but active_mm is swapper
+[ 9.742987] Internal error: Oops: 96000004 [#1] PREEMPT SMP
+[ 9.748614] Modules linked in:
+[ 9.751694] CPU: 16 PID: 293 Comm: kworker/16:1 Tainted: G W 4.19.0-rc4-next-20180920-00001-g9b0012c #322
+[ 9.762681] Hardware name: Huawei Taishan 2280 /D05, BIOS Hisilicon D05 IT21 Nemo 2.0 RC0 04/18/2018
+[ 9.771915] Workqueue: events work_for_cpu_fn
+[ 9.776312] pstate: 60000005 (nZCv daif -PAN -UAO)
+[ 9.781150] pc : drm_mode_object_put+0x0/0x20
+[ 9.785547] lr : hibmc_fbdev_fini+0x40/0x58
+[ 9.789767] sp : ffff00000af1bcf0
+[ 9.793108] x29: ffff00000af1bcf0 x28: 0000000000000000
+[ 9.798473] x27: 0000000000000000 x26: ffff000008f66630
+[ 9.803838] x25: 0000000000000000 x24: ffff0000095abb98
+[ 9.809203] x23: ffff8017db92fe00 x22: ffff8017d2b13000
+[ 9.814568] x21: ffffffffffffffea x20: ffff8017d2f80018
+[ 9.819933] x19: ffff8017d28a0018 x18: ffffffffffffffff
+[ 9.825297] x17: 0000000000000000 x16: 0000000000000000
+[ 9.830662] x15: ffff0000092296c8 x14: ffff00008939970f
+[ 9.836026] x13: ffff00000939971d x12: ffff000009229940
+[ 9.841391] x11: ffff0000085f8fc0 x10: ffff00000af1b9a0
+[ 9.846756] x9 : 000000000000000d x8 : 6620657a696c6169
+[ 9.852121] x7 : ffff8017d3340580 x6 : ffff8017d4168000
+[ 9.857486] x5 : 0000000000000000 x4 : ffff8017db92fb20
+[ 9.862850] x3 : 0000000000002690 x2 : ffff8017d3340480
+[ 9.868214] x1 : 0000000000000028 x0 : 0000000000000002
+[ 9.873580] Process kworker/16:1 (pid: 293, stack limit = 0x(____ptrval____))
+[ 9.880788] Call trace:
+[ 9.883252] drm_mode_object_put+0x0/0x20
+[ 9.887297] hibmc_unload+0x1c/0x80
+[ 9.890815] hibmc_pci_probe+0x170/0x3c8
+[ 9.894773] local_pci_probe+0x3c/0xb0
+[ 9.898555] work_for_cpu_fn+0x18/0x28
+[ 9.902337] process_one_work+0x1e0/0x318
+[ 9.906382] worker_thread+0x228/0x450
+[ 9.910164] kthread+0x128/0x130
+[ 9.913418] ret_from_fork+0x10/0x18
+[ 9.917024] Code: a94153f3 a8c27bfd d65f03c0 d503201f (f9400c01)
+[ 9.923180] ---[ end trace 2695ffa0af5be375 ]---
+
+Fixes: d1667b86795a ("drm/hisilicon/hibmc: Add support for frame buffer")
+Signed-off-by: John Garry <john.garry@huawei.com>
+Reviewed-by: Xinliang Liu <z.liuxinliang@hisilicon.com>
+Signed-off-by: Xinliang Liu <z.liuxinliang@hisilicon.com>
+Acked-by: Thomas Zimmermann <tzimmermann@suse.de>
+---
+ drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_fbdev.c | 1 +
+ 1 file changed, 1 insertion(+)
+
+diff --git a/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_fbdev.c b/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_fbdev.c
+index b92595c477ef..8bd29075ae4e 100644
+--- a/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_fbdev.c
++++ b/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_fbdev.c
+@@ -122,6 +122,7 @@ static int hibmc_drm_fb_create(struct drm_fb_helper *helper,
+ hi_fbdev->fb = hibmc_framebuffer_init(priv->dev, &mode_cmd, gobj);
+ if (IS_ERR(hi_fbdev->fb)) {
+ ret = PTR_ERR(hi_fbdev->fb);
++ hi_fbdev->fb = NULL;
+ DRM_ERROR("failed to initialize framebuffer: %d\n", ret);
+ goto out_release_fbi;
+ }
+--
+2.19.1
+
diff --git a/patches.fixes/0001-drm-hisilicon-hibmc-Don-t-overwrite-fb-helper-surfac.patch b/patches.fixes/0001-drm-hisilicon-hibmc-Don-t-overwrite-fb-helper-surfac.patch
new file mode 100644
index 0000000000..ba480ab984
--- /dev/null
+++ b/patches.fixes/0001-drm-hisilicon-hibmc-Don-t-overwrite-fb-helper-surfac.patch
@@ -0,0 +1,41 @@
+From 0ff9f49646353ce31312411e7e7bd2281492a40e Mon Sep 17 00:00:00 2001
+From: John Garry <john.garry@huawei.com>
+Date: Sat, 22 Sep 2018 01:25:26 +0800
+Subject: drm/hisilicon: hibmc: Don't overwrite fb helper surface depth
+Git-commit: 0ff9f49646353ce31312411e7e7bd2281492a40e
+Patch-mainline: v4.20-rc1
+References: bsc#1113766
+
+Currently the driver overwrites the surface depth provided by the fb
+helper to give an invalid bpp/surface depth combination.
+
+This has been exposed by commit 70109354fed2 ("drm: Reject unknown legacy
+bpp and depth for drm_mode_addfb ioctl"), which now causes the driver to
+fail to probe.
+
+Fix by not overwriting the surface depth.
+
+Fixes: d1667b86795a ("drm/hisilicon/hibmc: Add support for frame buffer")
+Signed-off-by: John Garry <john.garry@huawei.com>
+Reviewed-by: Xinliang Liu <z.liuxinliang@hisilicon.com>
+Signed-off-by: Xinliang Liu <z.liuxinliang@hisilicon.com>
+Acked-by: Thomas Zimmermann <tzimmermann@suse.de>
+---
+ drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_fbdev.c | 1 -
+ 1 file changed, 1 deletion(-)
+
+diff --git a/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_fbdev.c b/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_fbdev.c
+index 8bd29075ae4e..edcca1761500 100644
+--- a/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_fbdev.c
++++ b/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_fbdev.c
+@@ -71,7 +71,6 @@ static int hibmc_drm_fb_create(struct drm_fb_helper *helper,
+ DRM_DEBUG_DRIVER("surface width(%d), height(%d) and bpp(%d)\n",
+ sizes->surface_width, sizes->surface_height,
+ sizes->surface_bpp);
+- sizes->surface_depth = 32;
+
+ bytes_per_pixel = DIV_ROUND_UP(sizes->surface_bpp, 8);
+
+--
+2.19.1
+
diff --git a/patches.fixes/0001-drm-virtio-fix-bounds-check-in-virtio_gpu_cmd_get_ca.patch b/patches.fixes/0001-drm-virtio-fix-bounds-check-in-virtio_gpu_cmd_get_ca.patch
new file mode 100644
index 0000000000..ea1c9659fe
--- /dev/null
+++ b/patches.fixes/0001-drm-virtio-fix-bounds-check-in-virtio_gpu_cmd_get_ca.patch
@@ -0,0 +1,54 @@
+From 09c4b49457434fa74749ad6194ef28464d9f5df9 Mon Sep 17 00:00:00 2001
+From: Dan Carpenter <dan.carpenter@oracle.com>
+Date: Wed, 4 Jul 2018 12:42:50 +0300
+Subject: drm/virtio: fix bounds check in virtio_gpu_cmd_get_capset()
+Git-commit: 09c4b49457434fa74749ad6194ef28464d9f5df9
+Patch-mainline: v4.20-rc1
+References: bsc#1106929
+
+This doesn't affect runtime because in the current code "idx" is always
+valid.
+
+First, we read from "vgdev->capsets[idx].max_size" before checking
+whether "idx" is within bounds. And secondly the bounds check is off by
+one so we could end up reading one element beyond the end of the
+vgdev->capsets[] array.
+
+Fixes: 62fb7a5e1096 ("virtio-gpu: add 3d/virgl support")
+Signed-off-by: Dan Carpenter <dan.carpenter@oracle.com>
+Link: http://patchwork.freedesktop.org/patch/msgid/20180704094250.m7sgvvzg3dhcvv3h@kili.mountain
+Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
+Acked-by: Thomas Zimmermann <tzimmermann@suse.de>
+---
+ drivers/gpu/drm/virtio/virtgpu_vq.c | 5 +++--
+ 1 file changed, 3 insertions(+), 2 deletions(-)
+
+diff --git a/drivers/gpu/drm/virtio/virtgpu_vq.c b/drivers/gpu/drm/virtio/virtgpu_vq.c
+index 020070d483d3..4735bd1c7321 100644
+--- a/drivers/gpu/drm/virtio/virtgpu_vq.c
++++ b/drivers/gpu/drm/virtio/virtgpu_vq.c
+@@ -648,11 +648,11 @@ int virtio_gpu_cmd_get_capset(struct virtio_gpu_device *vgdev,
+ {
+ struct virtio_gpu_get_capset *cmd_p;
+ struct virtio_gpu_vbuffer *vbuf;
+- int max_size = vgdev->capsets[idx].max_size;
++ int max_size;
+ struct virtio_gpu_drv_cap_cache *cache_ent;
+ void *resp_buf;
+
+- if (idx > vgdev->num_capsets)
++ if (idx >= vgdev->num_capsets)
+ return -EINVAL;
+
+ if (version > vgdev->capsets[idx].max_version)
+@@ -662,6 +662,7 @@ int virtio_gpu_cmd_get_capset(struct virtio_gpu_device *vgdev,
+ if (!cache_ent)
+ return -ENOMEM;
+
++ max_size = vgdev->capsets[idx].max_size;
+ cache_ent->caps_cache = kmalloc(max_size, GFP_KERNEL);
+ if (!cache_ent->caps_cache) {
+ kfree(cache_ent);
+--
+2.19.1
+
diff --git a/patches.fixes/0001-fbdev-fix-broken-menu-dependencies.patch b/patches.fixes/0001-fbdev-fix-broken-menu-dependencies.patch
new file mode 100644
index 0000000000..3154a74ca2
--- /dev/null
+++ b/patches.fixes/0001-fbdev-fix-broken-menu-dependencies.patch
@@ -0,0 +1,113 @@
+From aae3394ef0ef90cf00a21133357448385f13a5d4 Mon Sep 17 00:00:00 2001
+From: Randy Dunlap <rdunlap@infradead.org>
+Date: Mon, 8 Oct 2018 12:57:36 +0200
+Subject: fbdev: fix broken menu dependencies
+Git-commit: aae3394ef0ef90cf00a21133357448385f13a5d4
+Patch-mainline: v4.20-rc1
+References: bsc#1106929
+
+The framebuffer options and devices menu is unintentionally split
+or broken because some items in it do not depend on FB (including
+several under omap and mmp).
+Fix this by moving FB_CMDLINE, FB_NOTIFY, and FB_CLPS711X_OLD to
+just before the FB Kconfig symbol definition and by moving the
+omap, omap2, and mmp menus to last, following FB_SM712.
+
+Also, the FB_VIA dependencies are duplicated by both being inside
+an "if FB_VIA/endif" block and "depends on FB_VIA", so drop the
+"depends on FB_VIA" lines since they are redundant.
+
+Fixes: ea6763c104c9 ("video/fbdev: Always built-in video= cmdline parsing")
+Fixes: 5ec9653806ba ("fbdev: Make fb-notify a no-op if CONFIG_FB=n")
+Fixes: ef74d46a4ef3 ("video: clps711x: Add new Cirrus Logic CLPS711X framebuffer driver")
+
+Backporting notes:
+
+ * Adapted patch to context changes.
+
+Signed-off-by: Randy Dunlap <rdunlap@infradead.org>
+Cc: Ezequiel Garcia <ezequiel@vanguardiasur.com.ar>
+Cc: Daniel Vetter <daniel.vetter@ffwll.ch>
+Cc: Alexander Shiyan <shc_work@mail.ru>
+Signed-off-by: Bartlomiej Zolnierkiewicz <b.zolnierkie@samsung.com>
+Acked-by: Thomas Zimmermann <tzimmermann@suse.de>
+---
+ drivers/video/fbdev/Kconfig | 65 +++++++++++++++++++++-----------------------
+ 1 file changed, 32 insertions(+), 33 deletions(-)
+
+--- a/drivers/video/fbdev/Kconfig
++++ b/drivers/video/fbdev/Kconfig
+@@ -2,6 +2,15 @@
+ # fbdev configuration
+ #
+
++config FB_CMDLINE
++ bool
++
++config FB_CLPS711X_OLD
++ tristate
++ select FB_CFB_FILLRECT
++ select FB_CFB_COPYAREA
++ select FB_CFB_IMAGEBLIT
++
+ menuconfig FB
+ tristate "Support for frame buffer devices"
+ select FB_CMDLINE
+@@ -53,9 +62,6 @@ config FIRMWARE_EDID
+ combination with certain motherboards and monitors are known to
+ suffer from this problem.
+
+-config FB_CMDLINE
+- bool
+-
+ config FB_DDC
+ tristate
+ depends on FB
+@@ -313,12 +319,6 @@ config FB_ACORN
+ hardware found in Acorn RISC PCs and other ARM-based machines. If
+ unsure, say N.
+
+-config FB_CLPS711X_OLD
+- tristate
+- select FB_CFB_FILLRECT
+- select FB_CFB_COPYAREA
+- select FB_CFB_IMAGEBLIT
+-
+ config FB_CLPS711X
+ tristate "CLPS711X LCD support"
+ depends on FB && (ARCH_CLPS711X || COMPILE_TEST)
+@@ -1550,7 +1550,6 @@ if FB_VIA
+
+ config FB_VIA_DIRECT_PROCFS
+ bool "direct hardware access via procfs (DEPRECATED)(DANGEROUS)"
+- depends on FB_VIA
+ default n
+ help
+ Allow direct hardware access to some output registers via procfs.
+@@ -1560,7 +1559,6 @@ config FB_VIA_DIRECT_PROCFS
+
+ config FB_VIA_X_COMPATIBILITY
+ bool "X server compatibility"
+- depends on FB_VIA
+ default n
+ help
+ This option reduces the functionality (power saving, ...) of the
+@@ -2446,10 +2444,7 @@ config FB_SIMPLE
+ Configuration re: surface address, size, and format must be provided
+ through device tree, or plain old platform data.
+
+-source "drivers/video/fbdev/omap/Kconfig"
+-source "drivers/video/fbdev/omap2/Kconfig"
+ source "drivers/video/fbdev/exynos/Kconfig"
+-source "drivers/video/fbdev/mmp/Kconfig"
+
+ config FB_SH_MOBILE_MERAM
+ tristate "SuperH Mobile MERAM read ahead support"
+@@ -2492,3 +2487,7 @@ config FB_SM712
+ This driver is also available as a module. The module will be
+ called sm712fb. If you want to compile it as a module, say M
+ here and read <file:Documentation/kbuild/modules.txt>.
++
++source "drivers/video/fbdev/omap/Kconfig"
++source "drivers/video/fbdev/omap2/Kconfig"
++source "drivers/video/fbdev/mmp/Kconfig"
diff --git a/patches.fixes/0001-memory_hotplug-cond_resched-in-__remove_pages.patch b/patches.fixes/0001-memory_hotplug-cond_resched-in-__remove_pages.patch
new file mode 100644
index 0000000000..78362cb7f8
--- /dev/null
+++ b/patches.fixes/0001-memory_hotplug-cond_resched-in-__remove_pages.patch
@@ -0,0 +1,59 @@
+From dd33ad7b251f900481701b2a82d25de583867708 Mon Sep 17 00:00:00 2001
+From: Michal Hocko <mhocko@suse.com>
+Date: Fri, 2 Nov 2018 15:48:46 -0700
+Subject: [PATCH] memory_hotplug: cond_resched in __remove_pages
+Git-commit: dd33ad7b251f900481701b2a82d25de583867708
+Patch-mainline: v4.20-rc1
+References: bnc#1114178
+
+We have received a bug report that unbinding a large pmem (>1TB) can
+result in a soft lockup:
+
+ NMI watchdog: BUG: soft lockup - CPU#9 stuck for 23s! [ndctl:4365]
+ [...]
+ Supported: Yes
+ CPU: 9 PID: 4365 Comm: ndctl Not tainted 4.12.14-94.40-default #1 SLE12-SP4
+ Hardware name: Intel Corporation S2600WFD/S2600WFD, BIOS SE5C620.86B.01.00.0833.051120182255 05/11/2018
+ task: ffff9cce7d4410c0 task.stack: ffffbe9eb1bc4000
+ RIP: 0010:__put_page+0x62/0x80
+ Call Trace:
+ devm_memremap_pages_release+0x152/0x260
+ release_nodes+0x18d/0x1d0
+ device_release_driver_internal+0x160/0x210
+ unbind_store+0xb3/0xe0
+ kernfs_fop_write+0x102/0x180
+ __vfs_write+0x26/0x150
+ vfs_write+0xad/0x1a0
+ SyS_write+0x42/0x90
+ do_syscall_64+0x74/0x150
+ entry_SYSCALL_64_after_hwframe+0x3d/0xa2
+ RIP: 0033:0x7fd13166b3d0
+
+It has been reported on an older (4.12) kernel but the current upstream
+code doesn't cond_resched in the hot remove code at all and the given
+range to remove might be really large. Fix the issue by calling
+cond_resched once per memory section.
+
+Link: http://lkml.kernel.org/r/20181031125840.23982-1-mhocko@kernel.org
+Signed-off-by: Michal Hocko <mhocko@suse.com>
+Acked-by: Johannes Thumshirn <jthumshirn@suse.de>
+Cc: Dan Williams <dan.j.williams@gmail.com>
+Cc: <stable@vger.kernel.org>
+Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
+Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
+
+---
+ mm/memory_hotplug.c | 2 ++
+ 1 file changed, 2 insertions(+)
+
+--- a/mm/memory_hotplug.c
++++ b/mm/memory_hotplug.c
+@@ -608,6 +608,8 @@ int __remove_pages(struct zone *zone, un
+ sections_to_remove = nr_pages / PAGES_PER_SECTION;
+ for (i = 0; i < sections_to_remove; i++) {
+ unsigned long pfn = phys_start_pfn + i*PAGES_PER_SECTION;
++
++ cond_resched();
+ ret = __remove_section(zone, __pfn_to_section(pfn));
+ if (ret)
+ break;
diff --git a/patches.fixes/0002-btrfs-Ensure-btrfs_trim_fs-can-trim-the-whole-filesy.patch b/patches.fixes/0002-btrfs-Ensure-btrfs_trim_fs-can-trim-the-whole-filesy.patch
new file mode 100644
index 0000000000..a8e6f838ba
--- /dev/null
+++ b/patches.fixes/0002-btrfs-Ensure-btrfs_trim_fs-can-trim-the-whole-filesy.patch
@@ -0,0 +1,97 @@
+From 6ba9fc8e628becf0e3ec94083450d089b0dec5f5 Mon Sep 17 00:00:00 2001
+From: Qu Wenruo <wqu@suse.com>
+Date: Fri, 7 Sep 2018 14:16:24 +0800
+Patch-mainline: v4.20
+Git-commit: 6ba9fc8e628becf0e3ec94083450d089b0dec5f5
+References: bsc#1113667
+Subject: [PATCH 2/2] btrfs: Ensure btrfs_trim_fs can trim the whole filesystem
+
+[BUG]
+fstrim on some btrfs only trims the unallocated space, not trimming any
+space in existing block groups.
+
+[CAUSE]
+Before fstrim_range passed to btrfs_trim_fs(), it gets truncated to
+range [0, super->total_bytes). So later btrfs_trim_fs() will only be
+able to trim block groups in range [0, super->total_bytes).
+
+While for btrfs, any bytenr aligned to sectorsize is valid, since btrfs
+uses its logical address space, there is nothing limiting the location
+where we put block groups.
+
+For filesystem with frequent balance, it's quite easy to relocate all
+block groups and bytenr of block groups will start beyond
+super->total_bytes.
+
+In that case, btrfs will not trim existing block groups.
+
+[FIX]
+Just remove the truncation in btrfs_ioctl_fitrim(), so btrfs_trim_fs()
+can get the unmodified range, which is normally set to [0, U64_MAX].
+
+Reported-by: Chris Murphy <lists@colorremedies.com>
+Fixes: f4c697e6406d ("btrfs: return EINVAL if start > total_bytes in fitrim ioctl")
+CC: <stable@vger.kernel.org> # v4.4+
+Signed-off-by: Qu Wenruo <wqu@suse.com>
+Reviewed-by: Nikolay Borisov <nborisov@suse.com>
+Reviewed-by: David Sterba <dsterba@suse.com>
+Signed-off-by: David Sterba <dsterba@suse.com>
+---
+ fs/btrfs/extent-tree.c | 10 +---------
+ fs/btrfs/ioctl.c | 11 +++++++----
+ 2 files changed, 8 insertions(+), 13 deletions(-)
+
+--- a/fs/btrfs/extent-tree.c
++++ b/fs/btrfs/extent-tree.c
+@@ -11037,21 +11037,13 @@ int btrfs_trim_fs(struct btrfs_root *roo
+ u64 start;
+ u64 end;
+ u64 trimmed = 0;
+- u64 total_bytes = btrfs_super_total_bytes(fs_info->super_copy);
+ u64 bg_failed = 0;
+ u64 dev_failed = 0;
+ int bg_ret = 0;
+ int dev_ret = 0;
+ int ret = 0;
+
+- /*
+- * try to trim all FS space, our block group may start from non-zero.
+- */
+- if (range->len == total_bytes)
+- cache = btrfs_lookup_first_block_group(fs_info, range->start);
+- else
+- cache = btrfs_lookup_block_group(fs_info, range->start);
+-
++ cache = btrfs_lookup_first_block_group(fs_info, range->start);
+ for (; cache; cache = next_block_group(root, cache)) {
+ if (cache->key.objectid >= (range->start + range->len)) {
+ btrfs_put_block_group(cache);
+--- a/fs/btrfs/ioctl.c
++++ b/fs/btrfs/ioctl.c
+@@ -379,7 +379,6 @@ static noinline int btrfs_ioctl_fitrim(s
+ struct fstrim_range range;
+ u64 minlen = ULLONG_MAX;
+ u64 num_devices = 0;
+- u64 total_bytes = btrfs_super_total_bytes(fs_info->super_copy);
+ int ret;
+
+ if (!capable(CAP_SYS_ADMIN))
+@@ -403,11 +402,15 @@ static noinline int btrfs_ioctl_fitrim(s
+ return -EOPNOTSUPP;
+ if (copy_from_user(&range, arg, sizeof(range)))
+ return -EFAULT;
+- if (range.start > total_bytes ||
+- range.len < fs_info->sb->s_blocksize)
++
++ /*
++ * NOTE: Don't truncate the range using super->total_bytes. Bytenr of
++ * block group is in the logical address space, which can be any
++ * sectorsize aligned bytenr in the range [0, U64_MAX].
++ */
++ if (range.len < fs_info->sb->s_blocksize)
+ return -EINVAL;
+
+- range.len = min(range.len, total_bytes - range.start);
+ range.minlen = max(range.minlen, minlen);
+ ret = btrfs_trim_fs(fs_info->tree_root, &range);
+ if (ret < 0)
diff --git a/patches.fixes/CIFS-511c54a2f69195b28afb9dd119f03787b1625bb4-adds-a-check-for-sess.patch b/patches.fixes/CIFS-511c54a2f69195b28afb9dd119f03787b1625bb4-adds-a-check-for-sess.patch
new file mode 100644
index 0000000000..5dbbef23ca
--- /dev/null
+++ b/patches.fixes/CIFS-511c54a2f69195b28afb9dd119f03787b1625bb4-adds-a-check-for-sess.patch
@@ -0,0 +1,33 @@
+From: Mark Syms <mark.syms@citrix.com>
+Date: Thu, 24 May 2018 09:47:31 +0100
+Subject: [PATCH] CIFS: check for STATUS_USER_SESSION_DELETED
+Git-commit: d81243c697ffc71f983736e7da2db31a8be0001f
+Patch-mainline: v4.17
+References: bsc#1112902
+
+Handle this additional status in the same way as SESSION_EXPIRED.
+
+Signed-off-by: Mark Syms <mark.syms@citrix.com>
+Signed-off-by: Steve French <stfrench@microsoft.com>
+CC: Stable <stable@vger.kernel.org>
+Acked-by: Aurelien Aptel <aaptel@suse.com>
+---
+ fs/cifs/smb2ops.c | 5 +++--
+ 1 file changed, 3 insertions(+), 2 deletions(-)
+
+--- a/fs/cifs/smb2ops.c
++++ b/fs/cifs/smb2ops.c
+@@ -1038,10 +1038,11 @@ smb2_is_session_expired(char *buf)
+ {
+ struct smb2_sync_hdr *shdr = get_sync_hdr(buf);
+
+- if (shdr->Status != STATUS_NETWORK_SESSION_EXPIRED)
++ if (shdr->Status != STATUS_NETWORK_SESSION_EXPIRED &&
++ shdr->Status != STATUS_USER_SESSION_DELETED)
+ return false;
+
+- cifs_dbg(FYI, "Session expired\n");
++ cifs_dbg(FYI, "Session expired or deleted\n");
+ return true;
+ }
+
diff --git a/patches.fixes/cdrom-fix-improper-type-cast-which-can-leat-to-infor.patch b/patches.fixes/cdrom-fix-improper-type-cast-which-can-leat-to-infor.patch
new file mode 100644
index 0000000000..467a42aa35
--- /dev/null
+++ b/patches.fixes/cdrom-fix-improper-type-cast-which-can-leat-to-infor.patch
@@ -0,0 +1,38 @@
+From e4f3aa2e1e67bb48dfbaaf1cad59013d5a5bc276 Mon Sep 17 00:00:00 2001
+From: Young_X <YangX92@hotmail.com>
+Date: Wed, 3 Oct 2018 12:54:29 +0000
+Subject: [PATCH] cdrom: fix improper type cast, which can leat to information leak.
+Git-commit: e4f3aa2e1e67bb48dfbaaf1cad59013d5a5bc276
+Patch-mainline: v4.20-rc1
+References: CVE-2018-18710,bsc#1113751
+
+There is another cast from unsigned long to int which causes
+a bounds check to fail with specially crafted input. The value is
+then used as an index in the slot array in cdrom_slot_status().
+
+This issue is similar to CVE-2018-16658 and CVE-2018-10940.
+
+Signed-off-by: Young_X <YangX92@hotmail.com>
+Signed-off-by: Jens Axboe <axboe@kernel.dk>
+Acked-by: Takashi Iwai <tiwai@suse.de>
+
+---
+ drivers/cdrom/cdrom.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/drivers/cdrom/cdrom.c b/drivers/cdrom/cdrom.c
+index a5d5a96479bf..10802d1fc554 100644
+--- a/drivers/cdrom/cdrom.c
++++ b/drivers/cdrom/cdrom.c
+@@ -2445,7 +2445,7 @@ static int cdrom_ioctl_select_disc(struct cdrom_device_info *cdi,
+ return -ENOSYS;
+
+ if (arg != CDSL_CURRENT && arg != CDSL_NONE) {
+- if ((int)arg >= cdi->capacity)
++ if (arg >= cdi->capacity)
+ return -EINVAL;
+ }
+
+--
+2.19.1
+
diff --git a/patches.fixes/cifs-Fix-use-after-free-of-a-mid_q_entry.patch b/patches.fixes/cifs-Fix-use-after-free-of-a-mid_q_entry.patch
new file mode 100644
index 0000000000..50c1b082bd
--- /dev/null
+++ b/patches.fixes/cifs-Fix-use-after-free-of-a-mid_q_entry.patch
@@ -0,0 +1,188 @@
+From: Lars Persson <lars.persson@axis.com>
+Date: Mon, 25 Jun 2018 14:05:25 +0200
+Subject: [PATCH] cifs: Fix use after free of a mid_q_entry
+Git-commit: 696e420bb2a6624478105651d5368d45b502b324
+Patch-mainline: v4.18-rc4
+References: bsc#1112903
+
+With protocol version 2.0 mounts we have seen crashes with corrupt mid
+entries. Either the server->pending_mid_q list becomes corrupt with a
+cyclic reference in one element or a mid object fetched by the
+demultiplexer thread becomes overwritten during use.
+
+Code review identified a race between the demultiplexer thread and the
+request issuing thread. The demultiplexer thread seems to be written
+with the assumption that it is the sole user of the mid object until
+it calls the mid callback which either wakes the issuer task or
+deletes the mid.
+
+This assumption is not true because the issuer task can be woken up
+earlier by a signal. If the demultiplexer thread has proceeded as far
+as setting the mid_state to MID_RESPONSE_RECEIVED then the issuer
+thread will happily end up calling cifs_delete_mid while the
+demultiplexer thread still is using the mid object.
+
+Inserting a delay in the cifs demultiplexer thread widens the race
+window and makes reproduction of the race very easy:
+
+ if (server->large_buf)
+ buf = server->bigbuf;
+
++ usleep_range(500, 4000);
+
+ server->lstrp = jiffies;
+
+To resolve this I think the proper solution involves putting a
+reference count on the mid object. This patch makes sure that the
+demultiplexer thread holds a reference until it has finished
+processing the transaction.
+
+Cc: stable@vger.kernel.org
+Signed-off-by: Lars Persson <larper@axis.com>
+Acked-by: Paulo Alcantara <palcantara@suse.de>
+Reviewed-by: Ronnie Sahlberg <lsahlber@redhat.com>
+Reviewed-by: Pavel Shilovsky <pshilov@microsoft.com>
+Signed-off-by: Steve French <stfrench@microsoft.com>
+Acked-by: Aurelien Aptel <aaptel@suse.com>
+---
+ fs/cifs/cifsglob.h | 1 +
+ fs/cifs/cifsproto.h | 1 +
+ fs/cifs/connect.c | 8 +++++++-
+ fs/cifs/smb1ops.c | 1 +
+ fs/cifs/smb2ops.c | 1 +
+ fs/cifs/smb2transport.c | 3 ++-
+ fs/cifs/transport.c | 18 +++++++++++++++++-
+ 7 files changed, 30 insertions(+), 3 deletions(-)
+
+--- a/fs/cifs/cifsglob.h
++++ b/fs/cifs/cifsglob.h
+@@ -1302,6 +1302,7 @@ typedef int (mid_handle_t)(struct TCP_Se
+ /* one of these for every pending CIFS request to the server */
+ struct mid_q_entry {
+ struct list_head qhead; /* mids waiting on reply from this server */
++ struct kref refcount;
+ struct TCP_Server_Info *server; /* server corresponding to this mid */
+ __u64 mid; /* multiplex id */
+ __u32 pid; /* process id */
+--- a/fs/cifs/cifsproto.h
++++ b/fs/cifs/cifsproto.h
+@@ -74,6 +74,7 @@ extern struct mid_q_entry *AllocMidQEntr
+ struct TCP_Server_Info *server);
+ extern void DeleteMidQEntry(struct mid_q_entry *midEntry);
+ extern void cifs_delete_mid(struct mid_q_entry *mid);
++extern void cifs_mid_q_entry_release(struct mid_q_entry *midEntry);
+ extern void cifs_wake_up_task(struct mid_q_entry *mid);
+ extern int cifs_handle_standard(struct TCP_Server_Info *server,
+ struct mid_q_entry *mid);
+--- a/fs/cifs/connect.c
++++ b/fs/cifs/connect.c
+@@ -883,6 +883,7 @@ cifs_demultiplex_thread(void *p)
+ continue;
+ server->total_read += length;
+
++ mid_entry = NULL;
+ if (server->ops->is_transform_hdr &&
+ server->ops->receive_transform &&
+ server->ops->is_transform_hdr(buf)) {
+@@ -897,8 +898,11 @@ cifs_demultiplex_thread(void *p)
+ length = mid_entry->receive(server, mid_entry);
+ }
+
+- if (length < 0)
++ if (length < 0) {
++ if (mid_entry)
++ cifs_mid_q_entry_release(mid_entry);
+ continue;
++ }
+
+ if (server->large_buf)
+ buf = server->bigbuf;
+@@ -914,6 +918,8 @@ cifs_demultiplex_thread(void *p)
+
+ if (!mid_entry->multiRsp || mid_entry->multiEnd)
+ mid_entry->callback(mid_entry);
++
++ cifs_mid_q_entry_release(mid_entry);
+ } else if (server->ops->is_oplock_break &&
+ server->ops->is_oplock_break(buf, server)) {
+ cifs_dbg(FYI, "Received oplock break\n");
+--- a/fs/cifs/smb1ops.c
++++ b/fs/cifs/smb1ops.c
+@@ -105,6 +105,7 @@ cifs_find_mid(struct TCP_Server_Info *se
+ if (compare_mid(mid->mid, buf) &&
+ mid->mid_state == MID_REQUEST_SUBMITTED &&
+ le16_to_cpu(mid->command) == buf->Command) {
++ kref_get(&mid->refcount);
+ spin_unlock(&GlobalMid_Lock);
+ return mid;
+ }
+--- a/fs/cifs/smb2ops.c
++++ b/fs/cifs/smb2ops.c
+@@ -197,6 +197,7 @@ smb2_find_mid(struct TCP_Server_Info *se
+ if ((mid->mid == wire_mid) &&
+ (mid->mid_state == MID_REQUEST_SUBMITTED) &&
+ (mid->command == shdr->Command)) {
++ kref_get(&mid->refcount);
+ spin_unlock(&GlobalMid_Lock);
+ return mid;
+ }
+--- a/fs/cifs/smb2transport.c
++++ b/fs/cifs/smb2transport.c
+@@ -433,7 +433,7 @@ smb3_calc_signature(struct smb_rqst *rqs
+ cifs_dbg(VFS, "%s: Could not init cmac aes\n", __func__);
+ return rc;
+ }
+-
++
+ rc = __cifs_calc_signature(rqst, server, sigptr,
+ &server->secmech.sdesccmacaes->shash);
+
+@@ -542,6 +542,7 @@ smb2_mid_entry_alloc(const struct smb2_s
+ return temp;
+ else {
+ memset(temp, 0, sizeof(struct mid_q_entry));
++ kref_init(&temp->refcount);
+ temp->mid = le64_to_cpu(shdr->MessageId);
+ temp->pid = current->pid;
+ temp->command = shdr->Command; /* Always LE */
+--- a/fs/cifs/transport.c
++++ b/fs/cifs/transport.c
+@@ -58,6 +58,7 @@ AllocMidQEntry(const struct smb_hdr *smb
+ return temp;
+ else {
+ memset(temp, 0, sizeof(struct mid_q_entry));
++ kref_init(&temp->refcount);
+ temp->mid = get_mid(smb_buffer);
+ temp->pid = current->pid;
+ temp->command = cpu_to_le16(smb_buffer->Command);
+@@ -80,6 +81,21 @@ AllocMidQEntry(const struct smb_hdr *smb
+ return temp;
+ }
+
++static void _cifs_mid_q_entry_release(struct kref *refcount)
++{
++ struct mid_q_entry *mid = container_of(refcount, struct mid_q_entry,
++ refcount);
++
++ mempool_free(mid, cifs_mid_poolp);
++}
++
++void cifs_mid_q_entry_release(struct mid_q_entry *midEntry)
++{
++ spin_lock(&GlobalMid_Lock);
++ kref_put(&midEntry->refcount, _cifs_mid_q_entry_release);
++ spin_unlock(&GlobalMid_Lock);
++}
++
+ void
+ DeleteMidQEntry(struct mid_q_entry *midEntry)
+ {
+@@ -108,7 +124,7 @@ DeleteMidQEntry(struct mid_q_entry *midE
+ }
+ }
+ #endif
+- mempool_free(midEntry, cifs_mid_poolp);
++ cifs_mid_q_entry_release(midEntry);
+ }
+
+ void
diff --git a/patches.fixes/cifs-fix-memory-leak-in-SMB2_open-.patch b/patches.fixes/cifs-fix-memory-leak-in-SMB2_open-.patch
new file mode 100644
index 0000000000..ab4b86d3de
--- /dev/null
+++ b/patches.fixes/cifs-fix-memory-leak-in-SMB2_open-.patch
@@ -0,0 +1,47 @@
+From: Ronnie Sahlberg <lsahlber@redhat.com>
+Date: Tue, 13 Feb 2018 15:42:30 +1100
+Subject: [PATCH] cifs: fix memory leak in SMB2_open()
+Git-commit: b7a73c84eb96dabd6bb8e9d7c56f796d83efee8e
+Patch-mainline: v4.17-rc1
+References: bsc#1112894
+
+Signed-off-by: Ronnie Sahlberg <lsahlber@redhat.com>
+Signed-off-by: Steve French <smfrench@gmail.com>
+CC: Stable <stable@vger.kernel.org>
+Acked-by: Aurelien Aptel <aaptel@suse.com>
+---
+ fs/cifs/smb2pdu.c | 8 ++++++--
+ 1 file changed, 6 insertions(+), 2 deletions(-)
+
+diff --git a/fs/cifs/smb2pdu.c b/fs/cifs/smb2pdu.c
+index 63778ac22fd9..ab4c20687cc0 100644
+--- a/fs/cifs/smb2pdu.c
++++ b/fs/cifs/smb2pdu.c
+@@ -1738,8 +1738,10 @@ SMB2_open(const unsigned int xid, struct cifs_open_parms *oparms, __le16 *path,
+ rc = alloc_path_with_tree_prefix(&copy_path, &copy_size,
+ &name_len,
+ tcon->treeName, path);
+- if (rc)
++ if (rc) {
++ cifs_small_buf_release(req);
+ return rc;
++ }
+ req->NameLength = cpu_to_le16(name_len * 2);
+ uni_path_len = copy_size;
+ path = copy_path;
+@@ -1750,8 +1752,10 @@ SMB2_open(const unsigned int xid, struct cifs_open_parms *oparms, __le16 *path,
+ if (uni_path_len % 8 != 0) {
+ copy_size = roundup(uni_path_len, 8);
+ copy_path = kzalloc(copy_size, GFP_KERNEL);
+- if (!copy_path)
++ if (!copy_path) {
++ cifs_small_buf_release(req);
+ return -ENOMEM;
++ }
+ memcpy((char *)copy_path, (const char *)path,
+ uni_path_len);
+ uni_path_len = copy_size;
+--
+2.13.7
+
+
diff --git a/patches.fixes/edac-thunderx-fix-memory-leak-in-thunderx_l2c_threaded_isr.patch b/patches.fixes/edac-thunderx-fix-memory-leak-in-thunderx_l2c_threaded_isr.patch
new file mode 100644
index 0000000000..cbadb007ef
--- /dev/null
+++ b/patches.fixes/edac-thunderx-fix-memory-leak-in-thunderx_l2c_threaded_isr.patch
@@ -0,0 +1,44 @@
+From: Dan Carpenter <dan.carpenter@oracle.com>
+Date: Sat, 13 Oct 2018 13:28:43 +0300
+Subject: EDAC, thunderx: Fix memory leak in thunderx_l2c_threaded_isr()
+Git-commit: d8c27ba86a2fd806d3957e5a9b30e66dfca2a61d
+Patch-mainline: v4.20-rc1
+References: bsc#1114648
+
+Fix memory leak in L2c threaded interrupt handler.
+
+ [ bp: Rewrite commit message. ]
+
+Fixes: 41003396f932 ("EDAC, thunderx: Add Cavium ThunderX EDAC driver")
+Signed-off-by: Dan Carpenter <dan.carpenter@oracle.com>
+Signed-off-by: Borislav Petkov <bp@suse.de>
+CC: David Daney <david.daney@cavium.com>
+CC: Jan Glauber <jglauber@cavium.com>
+CC: Mauro Carvalho Chehab <mchehab@kernel.org>
+CC: Sergey Temerkhanov <s.temerkhanov@gmail.com>
+CC: linux-edac <linux-edac@vger.kernel.org>
+Link: http://lkml.kernel.org/r/20181013102843.GG16086@mwanda
+---
+ drivers/edac/thunderx_edac.c | 4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+--- a/drivers/edac/thunderx_edac.c
++++ b/drivers/edac/thunderx_edac.c
+@@ -1906,7 +1906,7 @@ static irqreturn_t thunderx_l2c_threaded
+ default:
+ dev_err(&l2c->pdev->dev, "Unsupported device: %04x\n",
+ l2c->pdev->device);
+- return IRQ_NONE;
++ goto err_free;
+ }
+
+ while (CIRC_CNT(l2c->ring_head, l2c->ring_tail,
+@@ -1928,7 +1928,7 @@ static irqreturn_t thunderx_l2c_threaded
+ l2c->ring_tail++;
+ }
+
+- return IRQ_HANDLED;
++ ret = IRQ_HANDLED;
+
+ err_free:
+ kfree(other);
diff --git a/patches.fixes/fs-aio-fix-the-increment-of-aio-nr-and-counting-agai.patch b/patches.fixes/fs-aio-fix-the-increment-of-aio-nr-and-counting-agai.patch
index 55199326f6..bd8aae4dd6 100644
--- a/patches.fixes/fs-aio-fix-the-increment-of-aio-nr-and-counting-agai.patch
+++ b/patches.fixes/fs-aio-fix-the-increment-of-aio-nr-and-counting-agai.patch
@@ -3,7 +3,7 @@ Date: Wed, 5 Jul 2017 10:53:16 -0300
Subject: fs: aio: fix the increment of aio-nr and counting against aio-max-nr
Patch-mainline: v4.14-rc1
Git-commit: 2a8a98673c13cb2a61a6476153acf8344adfa992
-References: bsc#1068075, bsc#1078921
+References: bsc#1068075, bsc#1078921, bsc#1104124
Currently, aio-nr is incremented in steps of 'num_possible_cpus() * 8'
for io_setup(nr_events, ..) with 'nr_events < num_possible_cpus() * 4':
diff --git a/patches.fixes/mremap-properly-flush-TLB-before-releasing-the-page.patch b/patches.fixes/mremap-properly-flush-TLB-before-releasing-the-page.patch
new file mode 100644
index 0000000000..d69ff881b9
--- /dev/null
+++ b/patches.fixes/mremap-properly-flush-TLB-before-releasing-the-page.patch
@@ -0,0 +1,104 @@
+From eb66ae030829605d61fbef1909ce310e29f78821 Mon Sep 17 00:00:00 2001
+From: Linus Torvalds <torvalds@linux-foundation.org>
+Date: Fri, 12 Oct 2018 15:22:59 -0700
+Subject: [PATCH] mremap: properly flush TLB before releasing the page
+Git-commit: eb66ae030829605d61fbef1909ce310e29f78821
+Patch-mainline: v4.19
+References: bnc#1113769, CVE-2018-18281
+
+Jann Horn points out that our TLB flushing was subtly wrong for the
+mremap() case. What makes mremap() special is that we don't follow the
+usual "add page to list of pages to be freed, then flush tlb, and then
+free pages". No, mremap() obviously just _moves_ the page from one page
+table location to another.
+
+That matters, because mremap() thus doesn't directly control the
+lifetime of the moved page with a freelist: instead, the lifetime of the
+page is controlled by the page table locking, that serializes access to
+the entry.
+
+As a result, we need to flush the TLB not just before releasing the lock
+for the source location (to avoid any concurrent accesses to the entry),
+but also before we release the destination page table lock (to avoid the
+TLB being flushed after somebody else has already done something to that
+page).
+
+This also makes the whole "need_flush" logic unnecessary, since we now
+always end up flushing the TLB for every valid entry.
+
+Reported-and-tested-by: Jann Horn <jannh@google.com>
+Acked-by: Will Deacon <will.deacon@arm.com>
+Tested-by: Ingo Molnar <mingo@kernel.org>
+Acked-by: Peter Zijlstra (Intel) <peterz@infradead.org>
+Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+Signed-off-by: Michal Hocko <mhocko@suse.com>
+
+---
+ mm/huge_memory.c | 2 ++
+ mm/mremap.c | 12 ++++--------
+ 2 files changed, 6 insertions(+), 8 deletions(-)
+
+--- a/mm/huge_memory.c
++++ b/mm/huge_memory.c
+@@ -1586,6 +1586,8 @@ int move_huge_pmd(struct vm_area_struct
+ set_pmd_at(mm, new_addr, new_pmd, pmd_mksoft_dirty(pmd));
+ if (new_ptl != old_ptl)
+ spin_unlock(new_ptl);
++
++ flush_tlb_range(vma, old_addr, old_addr + PMD_SIZE);
+ spin_unlock(old_ptl);
+ }
+ out:
+--- a/mm/mremap.c
++++ b/mm/mremap.c
+@@ -96,6 +96,7 @@ static void move_ptes(struct vm_area_str
+ struct mm_struct *mm = vma->vm_mm;
+ pte_t *old_pte, *new_pte, pte;
+ spinlock_t *old_ptl, *new_ptl;
++ unsigned long len = old_end - old_addr;
+
+ /*
+ * When need_rmap_locks is true, we take the i_mmap_rwsem and anon_vma
+@@ -149,6 +150,7 @@ static void move_ptes(struct vm_area_str
+ }
+
+ arch_leave_lazy_mmu_mode();
++ flush_tlb_range(vma, old_end - len, old_end);
+ if (new_ptl != old_ptl)
+ spin_unlock(new_ptl);
+ pte_unmap(new_pte - 1);
+@@ -168,7 +170,6 @@ unsigned long move_page_tables(struct vm
+ {
+ unsigned long extent, next, old_end;
+ pmd_t *old_pmd, *new_pmd;
+- bool need_flush = false;
+ unsigned long mmun_start; /* For mmu_notifiers */
+ unsigned long mmun_end; /* For mmu_notifiers */
+
+@@ -206,12 +207,10 @@ unsigned long move_page_tables(struct vm
+ if (need_rmap_locks)
+ anon_vma_unlock_write(vma->anon_vma);
+ }
+- if (err > 0) {
+- need_flush = true;
++ if (err > 0)
+ continue;
+- } else if (!err) {
++ else if (!err)
+ split_huge_page_pmd(vma, old_addr, old_pmd);
+- }
+ VM_BUG_ON(pmd_trans_huge(*old_pmd));
+ }
+ if (pmd_none(*new_pmd) && __pte_alloc(new_vma->vm_mm, new_vma,
+@@ -224,10 +223,7 @@ unsigned long move_page_tables(struct vm
+ extent = LATENCY_LIMIT;
+ move_ptes(vma, old_pmd, old_addr, old_addr + extent,
+ new_vma, new_pmd, new_addr, need_rmap_locks);
+- need_flush = true;
+ }
+- if (likely(need_flush))
+- flush_tlb_range(vma, old_end-len, old_addr);
+
+ mmu_notifier_invalidate_range_end(vma->vm_mm, mmun_start, mmun_end);
+
diff --git a/patches.fixes/resource-include-resource-end-in-walk_-interfaces.patch b/patches.fixes/resource-include-resource-end-in-walk_-interfaces.patch
new file mode 100644
index 0000000000..8dcdf2ea1a
--- /dev/null
+++ b/patches.fixes/resource-include-resource-end-in-walk_-interfaces.patch
@@ -0,0 +1,76 @@
+From: Bjorn Helgaas <bhelgaas@google.com>
+Date: Thu, 27 Sep 2018 09:22:02 -0500
+Subject: resource: Include resource end in walk_*() interfaces
+Git-commit: a98959fdbda1849a01b2150bb635ed559ec06700
+Patch-mainline: v4.20-rc1
+References: bsc#1114648
+
+find_next_iomem_res() finds an iomem resource that covers part of a range
+described by "start, end". All callers expect that range to be inclusive,
+i.e., both start and end are included, but find_next_iomem_res() doesn't
+handle the end address correctly.
+
+If it finds an iomem resource that contains exactly the end address, it
+skips it, e.g., if "start, end" is [0x0-0x10000] and there happens to be an
+iomem resource [mem 0x10000-0x10000] (the single byte at 0x10000), we skip
+it:
+
+ find_next_iomem_res(...)
+ {
+ start = 0x0;
+ end = 0x10000;
+ for (p = next_resource(...)) {
+ # p->start = 0x10000;
+ # p->end = 0x10000;
+ # we *should* return this resource, but this condition is false:
+ if ((p->end >= start) && (p->start < end))
+ break;
+
+Adjust find_next_iomem_res() so it allows a resource that includes the
+single byte at the end of the range. This is a corner case that we
+probably don't see in practice.
+
+Fixes: 58c1b5b07907 ("[PATCH] memory hotadd fixes: find_next_system_ram catch range fix")
+Signed-off-by: Bjorn Helgaas <bhelgaas@google.com>
+Signed-off-by: Borislav Petkov <bp@suse.de>
+CC: Andrew Morton <akpm@linux-foundation.org>
+CC: Brijesh Singh <brijesh.singh@amd.com>
+CC: Dan Williams <dan.j.williams@intel.com>
+CC: H. Peter Anvin <hpa@zytor.com>
+CC: Lianbo Jiang <lijiang@redhat.com>
+CC: Takashi Iwai <tiwai@suse.de>
+CC: Thomas Gleixner <tglx@linutronix.de>
+CC: Tom Lendacky <thomas.lendacky@amd.com>
+CC: Vivek Goyal <vgoyal@redhat.com>
+CC: Yaowei Bai <baiyaowei@cmss.chinamobile.com>
+CC: bhe@redhat.com
+CC: dan.j.williams@intel.com
+CC: dyoung@redhat.com
+CC: kexec@lists.infradead.org
+CC: mingo@redhat.com
+CC: x86-ml <x86@kernel.org>
+Link: http://lkml.kernel.org/r/153805812254.1157.16736368485811773752.stgit@bhelgaas-glaptop.roam.corp.google.com
+---
+ kernel/resource.c | 4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+--- a/kernel/resource.c
++++ b/kernel/resource.c
+@@ -343,7 +343,7 @@ int release_resource(struct resource *ol
+ EXPORT_SYMBOL(release_resource);
+
+ /*
+- * Finds the lowest iomem reosurce exists with-in [res->start.res->end)
++ * Finds the lowest iomem resource existing within [res->start..res->end].
+ * the caller must specify res->start, res->end, res->flags and "name".
+ * If found, returns 0, res is overwritten, if not found, returns -1.
+ * This walks through whole tree and not just first level children
+@@ -376,7 +376,7 @@ static int find_next_iomem_res(struct re
+ p = NULL;
+ break;
+ }
+- if ((p->end >= start) && (p->start < end))
++ if ((p->end >= start) && (p->start <= end))
+ break;
+ }
+
diff --git a/patches.fixes/smb3-fill-in-statfs-fsid-and-correct-namelen.patch b/patches.fixes/smb3-fill-in-statfs-fsid-and-correct-namelen.patch
new file mode 100644
index 0000000000..aea706672b
--- /dev/null
+++ b/patches.fixes/smb3-fill-in-statfs-fsid-and-correct-namelen.patch
@@ -0,0 +1,109 @@
+From: Steve French <stfrench@microsoft.com>
+Date: Sun, 24 Jun 2018 23:18:52 -0500
+Subject: [PATCH] smb3: fill in statfs fsid and correct namelen
+Git-commit: 21ba3845b59c733a79ed4fe1c4f3732e7ece9df7
+Patch-mainline: v4.18
+References: bsc#1112905
+
+Fil in the correct namelen (typically 255 not 4096) in the
+statfs response and also fill in a reasonably unique fsid
+(in this case taken from the volume id, and the creation time
+of the volume).
+
+In the case of the POSIX statfs all fields are now filled in,
+and in the case of non-POSIX mounts, all fields are filled
+in which can be.
+
+Signed-off-by: Steve French <stfrench@gmail.com>
+CC: Stable <stable@vger.kernel.org>
+Reviewed-by: Aurelien Aptel <aaptel@suse.com>
+Acked-by: Aurelien Aptel <aaptel@suse.com>
+---
+ fs/cifs/cifsfs.c | 18 ++++++++++--------
+ fs/cifs/smb2ops.c | 2 ++
+ fs/cifs/smb2pdu.c | 8 ++++++++
+ fs/cifs/smb2pdu.h | 11 +++++++++++
+ 4 files changed, 31 insertions(+), 8 deletions(-)
+
+--- a/fs/cifs/cifsfs.c
++++ b/fs/cifs/cifsfs.c
+@@ -199,14 +199,16 @@ cifs_statfs(struct dentry *dentry, struc
+
+ xid = get_xid();
+
+- /*
+- * PATH_MAX may be too long - it would presumably be total path,
+- * but note that some servers (includinng Samba 3) have a shorter
+- * maximum path.
+- *
+- * Instead could get the real value via SMB_QUERY_FS_ATTRIBUTE_INFO.
+- */
+- buf->f_namelen = PATH_MAX;
++ if (le32_to_cpu(tcon->fsAttrInfo.MaxPathNameComponentLength) > 0)
++ buf->f_namelen =
++ le32_to_cpu(tcon->fsAttrInfo.MaxPathNameComponentLength);
++ else
++ buf->f_namelen = PATH_MAX;
++
++ buf->f_fsid.val[0] = tcon->vol_serial_number;
++ /* are using part of create time for more randomness, see man statfs */
++ buf->f_fsid.val[1] = (int)le64_to_cpu(tcon->vol_create_time);
++
+ buf->f_files = 0; /* undefined */
+ buf->f_ffree = 0; /* unlimited */
+
+--- a/fs/cifs/smb2ops.c
++++ b/fs/cifs/smb2ops.c
+@@ -332,6 +332,8 @@ smb3_qfs_tcon(const unsigned int xid, st
+ SMB2_QFS_attr(xid, tcon, fid.persistent_fid, fid.volatile_fid,
+ FS_DEVICE_INFORMATION);
+ SMB2_QFS_attr(xid, tcon, fid.persistent_fid, fid.volatile_fid,
++ FS_VOLUME_INFORMATION);
++ SMB2_QFS_attr(xid, tcon, fid.persistent_fid, fid.volatile_fid,
+ FS_SECTOR_SIZE_INFORMATION); /* SMB3 specific */
+ SMB2_close(xid, tcon, fid.persistent_fid, fid.volatile_fid);
+ return;
+--- a/fs/cifs/smb2pdu.c
++++ b/fs/cifs/smb2pdu.c
+@@ -3316,6 +3316,9 @@ SMB2_QFS_attr(const unsigned int xid, st
+ } else if (level == FS_SECTOR_SIZE_INFORMATION) {
+ max_len = sizeof(struct smb3_fs_ss_info);
+ min_len = sizeof(struct smb3_fs_ss_info);
++ } else if (level == FS_VOLUME_INFORMATION) {
++ max_len = sizeof(struct smb3_fs_vol_info) + MAX_VOL_LABEL_LEN;
++ min_len = sizeof(struct smb3_fs_vol_info);
+ } else {
+ cifs_dbg(FYI, "Invalid qfsinfo level %d\n", level);
+ return -EINVAL;
+@@ -3356,6 +3359,11 @@ SMB2_QFS_attr(const unsigned int xid, st
+ tcon->ss_flags = le32_to_cpu(ss_info->Flags);
+ tcon->perf_sector_size =
+ le32_to_cpu(ss_info->PhysicalBytesPerSectorForPerf);
++ } else if (level == FS_VOLUME_INFORMATION) {
++ struct smb3_fs_vol_info *vol_info = (struct smb3_fs_vol_info *)
++ (offset + (char *)rsp);
++ tcon->vol_serial_number = vol_info->VolumeSerialNumber;
++ tcon->vol_create_time = vol_info->VolumeCreationTime;
+ }
+
+ qfsattr_exit:
+--- a/fs/cifs/smb2pdu.h
++++ b/fs/cifs/smb2pdu.h
+@@ -1106,6 +1106,17 @@ struct smb3_fs_ss_info {
+ __le32 ByteOffsetForPartitionAlignment;
+ } __packed;
+
++/* volume info struct - see MS-FSCC 2.5.9 */
++#define MAX_VOL_LABEL_LEN 32
++struct smb3_fs_vol_info {
++ __le64 VolumeCreationTime;
++ __u32 VolumeSerialNumber;
++ __le32 VolumeLabelLength; /* includes trailing null */
++ __u8 SupportsObjects; /* True if eg like NTFS, supports objects */
++ __u8 Reserved;
++ __u8 VolumeLabel[0]; /* variable len */
++} __packed;
++
+ /* partial list of QUERY INFO levels */
+ #define FILE_DIRECTORY_INFORMATION 1
+ #define FILE_FULL_DIRECTORY_INFORMATION 2
diff --git a/patches.fixes/x86-kexec-correct-kexec_backup_src_end-off-by-one-error.patch b/patches.fixes/x86-kexec-correct-kexec_backup_src_end-off-by-one-error.patch
new file mode 100644
index 0000000000..103f7bd752
--- /dev/null
+++ b/patches.fixes/x86-kexec-correct-kexec_backup_src_end-off-by-one-error.patch
@@ -0,0 +1,62 @@
+From: Bjorn Helgaas <bhelgaas@google.com>
+Date: Thu, 27 Sep 2018 09:21:55 -0500
+Subject: x86/kexec: Correct KEXEC_BACKUP_SRC_END off-by-one error
+Git-commit: 51fbf14f2528a8c6401290e37f1c893a2412f1d3
+Patch-mainline: v4.20-rc1
+References: bsc#1114648
+
+The only use of KEXEC_BACKUP_SRC_END is as an argument to
+walk_system_ram_res():
+
+ int crash_load_segments(struct kimage *image)
+ {
+ ...
+ walk_system_ram_res(KEXEC_BACKUP_SRC_START, KEXEC_BACKUP_SRC_END,
+ image, determine_backup_region);
+
+walk_system_ram_res() expects "start, end" arguments that are inclusive,
+i.e., the range to be walked includes both the start and end addresses.
+
+KEXEC_BACKUP_SRC_END was previously defined as (640 * 1024UL), which is the
+first address *past* the desired 0-640KB range.
+
+Define KEXEC_BACKUP_SRC_END as (640 * 1024UL - 1) so the KEXEC_BACKUP_SRC
+region is [0-0x9ffff], not [0-0xa0000].
+
+Fixes: dd5f726076cc ("kexec: support for kexec on panic using new system call")
+Signed-off-by: Bjorn Helgaas <bhelgaas@google.com>
+Signed-off-by: Borislav Petkov <bp@suse.de>
+CC: "H. Peter Anvin" <hpa@zytor.com>
+CC: Andrew Morton <akpm@linux-foundation.org>
+CC: Brijesh Singh <brijesh.singh@amd.com>
+CC: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+CC: Ingo Molnar <mingo@redhat.com>
+CC: Lianbo Jiang <lijiang@redhat.com>
+CC: Takashi Iwai <tiwai@suse.de>
+CC: Thomas Gleixner <tglx@linutronix.de>
+CC: Tom Lendacky <thomas.lendacky@amd.com>
+CC: Vivek Goyal <vgoyal@redhat.com>
+CC: baiyaowei@cmss.chinamobile.com
+CC: bhe@redhat.com
+CC: dan.j.williams@intel.com
+CC: dyoung@redhat.com
+CC: kexec@lists.infradead.org
+Link: http://lkml.kernel.org/r/153805811578.1157.6948388946904655969.stgit@bhelgaas-glaptop.roam.corp.google.com
+---
+ arch/x86/include/asm/kexec.h | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/arch/x86/include/asm/kexec.h b/arch/x86/include/asm/kexec.h
+index f327236f0fa7..5125fca472bb 100644
+--- a/arch/x86/include/asm/kexec.h
++++ b/arch/x86/include/asm/kexec.h
+@@ -67,7 +67,7 @@ struct kimage;
+
+ /* Memory to backup during crash kdump */
+ #define KEXEC_BACKUP_SRC_START (0UL)
+-#define KEXEC_BACKUP_SRC_END (640 * 1024UL) /* 640K */
++#define KEXEC_BACKUP_SRC_END (640 * 1024UL - 1) /* 640K */
+
+ /*
+ * CPU does not save ss and sp on stack if execution is already
+
diff --git a/patches.suse/0001-Btrfs-fix-invalid-attempt-to-free-reserved-space-on-.patch b/patches.suse/0001-Btrfs-fix-invalid-attempt-to-free-reserved-space-on-.patch
new file mode 100644
index 0000000000..2093af5e26
--- /dev/null
+++ b/patches.suse/0001-Btrfs-fix-invalid-attempt-to-free-reserved-space-on-.patch
@@ -0,0 +1,235 @@
+From a315e68f6e8b3006c29482dbfc4d928f098c449c Mon Sep 17 00:00:00 2001
+From: Filipe Manana <fdmanana@suse.com>
+Date: Mon, 6 Mar 2017 23:04:20 +0000
+Patch-mainline: v4.12
+Git-commit: a315e68f6e8b3006c29482dbfc4d928f098c449c
+References: dependency for bsc#1031392
+Subject: [PATCH] Btrfs: fix invalid attempt to free reserved space on failure
+ to cow range
+
+When attempting to COW a file range (we are starting writeback and doing
+COW), if we manage to reserve an extent for the range we will write into
+but fail after reserving it and before creating the respective ordered
+extent, we end up in an error path where we attempt to decrement the
+data space's bytes_may_use counter after we already did it while
+reserving the extent, leading to a warning/trace like the following:
+
+[ 847.621524] ------------[ cut here ]------------
+[ 847.625441] WARNING: CPU: 5 PID: 4905 at fs/btrfs/extent-tree.c:4316 btrfs_free_reserved_data_space_noquota+0x60/0x9f [btrfs]
+[ 847.633704] Modules linked in: btrfs crc32c_generic xor raid6_pq acpi_cpufreq i2c_piix4 ppdev psmouse tpm_tis serio_raw pcspkr parport_pc tpm_tis_core i2c_core sg
+[ 847.644616] CPU: 5 PID: 4905 Comm: xfs_io Not tainted 4.10.0-rc8-btrfs-next-37+ #2
+[ 847.648601] Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS rel-1.9.1-0-gb3ef39f-prebuilt.qemu-project.org 04/01/2014
+[ 847.648601] Call Trace:
+[ 847.648601] dump_stack+0x67/0x90
+[ 847.648601] __warn+0xc2/0xdd
+[ 847.648601] warn_slowpath_null+0x1d/0x1f
+[ 847.648601] btrfs_free_reserved_data_space_noquota+0x60/0x9f [btrfs]
+[ 847.648601] btrfs_clear_bit_hook+0x140/0x258 [btrfs]
+[ 847.648601] clear_state_bit+0x87/0x128 [btrfs]
+[ 847.648601] __clear_extent_bit+0x222/0x2b7 [btrfs]
+[ 847.648601] clear_extent_bit+0x17/0x19 [btrfs]
+[ 847.648601] extent_clear_unlock_delalloc+0x3b/0x6b [btrfs]
+[ 847.648601] cow_file_range.isra.39+0x387/0x39a [btrfs]
+[ 847.648601] run_delalloc_nocow+0x4d7/0x70e [btrfs]
+[ 847.648601] ? arch_local_irq_save+0x9/0xc
+[ 847.648601] run_delalloc_range+0xa7/0x2b5 [btrfs]
+[ 847.648601] writepage_delalloc.isra.31+0xb9/0x15c [btrfs]
+[ 847.648601] __extent_writepage+0x249/0x2e8 [btrfs]
+[ 847.648601] extent_write_cache_pages.constprop.33+0x28b/0x36c [btrfs]
+[ 847.648601] ? arch_local_irq_save+0x9/0xc
+[ 847.648601] ? mark_lock+0x24/0x201
+[ 847.648601] extent_writepages+0x4b/0x5c [btrfs]
+[ 847.648601] ? btrfs_writepage_start_hook+0xed/0xed [btrfs]
+[ 847.648601] btrfs_writepages+0x28/0x2a [btrfs]
+[ 847.648601] do_writepages+0x23/0x2c
+[ 847.648601] __filemap_fdatawrite_range+0x5a/0x61
+[ 847.648601] filemap_fdatawrite_range+0x13/0x15
+[ 847.648601] btrfs_fdatawrite_range+0x20/0x46 [btrfs]
+[ 847.648601] start_ordered_ops+0x19/0x23 [btrfs]
+[ 847.648601] btrfs_sync_file+0x136/0x42c [btrfs]
+[ 847.648601] vfs_fsync_range+0x8c/0x9e
+[ 847.648601] vfs_fsync+0x1c/0x1e
+[ 847.648601] do_fsync+0x31/0x4a
+[ 847.648601] SyS_fsync+0x10/0x14
+[ 847.648601] entry_SYSCALL_64_fastpath+0x18/0xad
+[ 847.648601] RIP: 0033:0x7f5b05200800
+[ 847.648601] RSP: 002b:00007ffe204f71c8 EFLAGS: 00000246 ORIG_RAX: 000000000000004a
+[ 847.648601] RAX: ffffffffffffffda RBX: ffffffff8109637b RCX: 00007f5b05200800
+[ 847.648601] RDX: 00000000008bd0a0 RSI: 00000000008bd2e0 RDI: 0000000000000003
+[ 847.648601] RBP: ffffc90001d67f98 R08: 000000000000ffff R09: 000000000000001f
+[ 847.648601] R10: 00000000000001f6 R11: 0000000000000246 R12: 0000000000000046
+[ 847.648601] R13: ffffc90001d67f78 R14: 00007f5b054be740 R15: 00007f5b054be740
+[ 847.648601] ? trace_hardirqs_off_caller+0x3f/0xaa
+[ 847.685787] ---[ end trace 2a4a3e15382508e8 ]---
+
+So fix this by not attempting to decrement the data space info's
+bytes_may_use counter if we already reserved the extent and an error
+happened before creating the ordered extent. We are already correctly
+freeing the reserved extent if an error happens, so there's no additional
+measure needed.
+
+Signed-off-by: Filipe Manana <fdmanana@suse.com>
+Reviewed-by: Liu Bo <bo.li.liu@oracle.com>
+---
+ fs/btrfs/extent_io.h | 4 ++-
+ fs/btrfs/inode.c | 59 ++++++++++++++++++++++++++++++++++++---------------
+ 2 files changed, 45 insertions(+), 18 deletions(-)
+
+--- a/fs/btrfs/extent_io.h
++++ b/fs/btrfs/extent_io.h
+@@ -14,7 +14,7 @@
+ #define EXTENT_DEFRAG (1U << 6)
+ #define EXTENT_BOUNDARY (1U << 9)
+ #define EXTENT_NODATASUM (1U << 10)
+-#define EXTENT_DO_ACCOUNTING (1U << 11)
++#define EXTENT_CLEAR_META_RESV (1U << 11)
+ #define EXTENT_FIRST_DELALLOC (1U << 12)
+ #define EXTENT_NEED_WAIT (1U << 13)
+ #define EXTENT_DAMAGED (1U << 14)
+@@ -22,6 +22,8 @@
+ #define EXTENT_QGROUP_RESERVED (1U << 16)
+ #define EXTENT_CLEAR_DATA_RESV (1U << 17)
+ #define EXTENT_IOBITS (EXTENT_LOCKED | EXTENT_WRITEBACK)
++#define EXTENT_DO_ACCOUNTING (EXTENT_CLEAR_META_RESV | \
++ EXTENT_CLEAR_DATA_RESV)
+ #define EXTENT_CTLBITS (EXTENT_DO_ACCOUNTING | EXTENT_FIRST_DELALLOC)
+
+ /*
+--- a/fs/btrfs/inode.c
++++ b/fs/btrfs/inode.c
+@@ -945,11 +945,14 @@ static noinline int cow_file_range(struc
+ u64 num_bytes;
+ unsigned long ram_size;
+ u64 disk_num_bytes;
+- u64 cur_alloc_size;
++ u64 cur_alloc_size = 0;
+ u64 blocksize = root->sectorsize;
+ struct btrfs_key ins;
+ struct extent_map *em;
+ struct extent_map_tree *em_tree = &BTRFS_I(inode)->extent_tree;
++ unsigned clear_bits;
++ unsigned long page_ops;
++ bool extent_reserved = false;
+ int ret = 0;
+
+ if (btrfs_is_free_space_inode(inode)) {
+@@ -997,14 +1000,14 @@ static noinline int cow_file_range(struc
+ btrfs_drop_extent_cache(inode, start, start + num_bytes - 1, 0);
+
+ while (disk_num_bytes > 0) {
+- unsigned long op;
+-
+ cur_alloc_size = disk_num_bytes;
+ ret = btrfs_reserve_extent(root, cur_alloc_size, cur_alloc_size,
+ root->sectorsize, 0, alloc_hint,
+ &ins, 1, 1);
+ if (ret < 0)
+ goto out_unlock;
++ cur_alloc_size = ins.offset;
++ extent_reserved = true;
+
+ em = alloc_extent_map();
+ if (!em) {
+@@ -1040,7 +1043,6 @@ static noinline int cow_file_range(struc
+ if (ret)
+ goto out_reserve;
+
+- cur_alloc_size = ins.offset;
+ ret = btrfs_add_ordered_extent(inode, start, ins.objectid,
+ ram_size, cur_alloc_size, 0);
+ if (ret)
+@@ -1066,18 +1068,19 @@ static noinline int cow_file_range(struc
+ * Do set the Private2 bit so we know this page was properly
+ * setup for writepage
+ */
+- op = unlock ? PAGE_UNLOCK : 0;
+- op |= PAGE_SET_PRIVATE2;
++ page_ops = unlock ? PAGE_UNLOCK : 0;
++ page_ops |= PAGE_SET_PRIVATE2;
+
+ extent_clear_unlock_delalloc(inode, start,
+ start + ram_size - 1,
+ delalloc_end, locked_page,
+ EXTENT_LOCKED | EXTENT_DELALLOC,
+- op);
++ page_ops);
+ disk_num_bytes -= cur_alloc_size;
+ num_bytes -= cur_alloc_size;
+ alloc_hint = ins.objectid + ins.offset;
+ start += cur_alloc_size;
++ extent_reserved = false;
+ }
+ out:
+ return ret;
+@@ -1088,12 +1091,35 @@ out_reserve:
+ btrfs_dec_block_group_reservations(root->fs_info, ins.objectid);
+ btrfs_free_reserved_extent(root, ins.objectid, ins.offset, 1);
+ out_unlock:
++ clear_bits = EXTENT_LOCKED | EXTENT_DELALLOC | EXTENT_DEFRAG |
++ EXTENT_CLEAR_META_RESV;
++ page_ops = PAGE_UNLOCK | PAGE_CLEAR_DIRTY | PAGE_SET_WRITEBACK |
++ PAGE_END_WRITEBACK;
++ /*
++ * If we reserved an extent for our delalloc range (or a subrange) and
++ * failed to create the respective ordered extent, then it means that
++ * when we reserved the extent we decremented the extent's size from
++ * the data space_info's bytes_may_use counter and incremented the
++ * space_info's bytes_reserved counter by the same amount. We must make
++ * sure extent_clear_unlock_delalloc() does not try to decrement again
++ * the data space_info's bytes_may_use counter, therefore we do not pass
++ * it the flag EXTENT_CLEAR_DATA_RESV.
++ */
++ if (extent_reserved) {
++ extent_clear_unlock_delalloc(inode, start,
++ start + cur_alloc_size,
++ start + cur_alloc_size,
++ locked_page,
++ clear_bits,
++ page_ops);
++ start += cur_alloc_size;
++ if (start >= end)
++ goto out;
++ }
+ extent_clear_unlock_delalloc(inode, start, end, delalloc_end,
+ locked_page,
+- EXTENT_LOCKED | EXTENT_DO_ACCOUNTING |
+- EXTENT_DELALLOC | EXTENT_DEFRAG,
+- PAGE_UNLOCK | PAGE_CLEAR_DIRTY |
+- PAGE_SET_WRITEBACK | PAGE_END_WRITEBACK);
++ clear_bits | EXTENT_CLEAR_DATA_RESV,
++ page_ops);
+ goto out;
+ }
+
+@@ -1809,7 +1835,7 @@ static void btrfs_clear_bit_hook(struct
+
+ if (*bits & EXTENT_FIRST_DELALLOC) {
+ *bits &= ~EXTENT_FIRST_DELALLOC;
+- } else if (!(*bits & EXTENT_DO_ACCOUNTING)) {
++ } else if (!(*bits & EXTENT_CLEAR_META_RESV)) {
+ spin_lock(&BTRFS_I(inode)->lock);
+ BTRFS_I(inode)->outstanding_extents -= num_extents;
+ spin_unlock(&BTRFS_I(inode)->lock);
+@@ -1820,7 +1846,7 @@ static void btrfs_clear_bit_hook(struct
+ * don't need to call dellalloc_release_metadata if there is an
+ * error.
+ */
+- if (*bits & EXTENT_DO_ACCOUNTING &&
++ if (*bits & EXTENT_CLEAR_META_RESV &&
+ root != root->fs_info->tree_root)
+ btrfs_delalloc_release_metadata(inode, len);
+
+@@ -1828,10 +1854,9 @@ static void btrfs_clear_bit_hook(struct
+ if (btrfs_test_is_dummy_root(root))
+ return;
+
+- if (root->root_key.objectid != BTRFS_DATA_RELOC_TREE_OBJECTID
+- && do_list && !(state->state & EXTENT_NORESERVE)
+- && (*bits & (EXTENT_DO_ACCOUNTING |
+- EXTENT_CLEAR_DATA_RESV)))
++ if (root->root_key.objectid != BTRFS_DATA_RELOC_TREE_OBJECTID &&
++ do_list && !(state->state & EXTENT_NORESERVE) &&
++ (*bits & EXTENT_CLEAR_DATA_RESV))
+ btrfs_free_reserved_data_space_noquota(inode,
+ state->start, len);
+
diff --git a/patches.suse/0001-Btrfs-pass-delayed_refs-directly-to-btrfs_find_delay.patch b/patches.suse/0001-Btrfs-pass-delayed_refs-directly-to-btrfs_find_delay.patch
new file mode 100644
index 0000000000..b044fbaae9
--- /dev/null
+++ b/patches.suse/0001-Btrfs-pass-delayed_refs-directly-to-btrfs_find_delay.patch
@@ -0,0 +1,101 @@
+From f72ad18e996338a8033aeb981e645f8dbf4e22c1 Mon Sep 17 00:00:00 2001
+From: Liu Bo <bo.li.liu@oracle.com>
+Date: Mon, 30 Jan 2017 12:24:37 -0800
+Patch-mainline: v4.11
+Git-commit: f72ad18e996338a8033aeb981e645f8dbf4e22c1
+References: dependency for bsc#1031392
+Subject: [PATCH 1/2] Btrfs: pass delayed_refs directly to
+ btrfs_find_delayed_ref_head
+
+All we need is @delayed_refs, all callers have get it ahead of calling
+btrfs_find_delayed_ref_head since lock needs to be acquired firstly,
+there is no reason to deference it again inside the function.
+
+Signed-off-by: Liu Bo <bo.li.liu@oracle.com>
+Reviewed-by: David Sterba <dsterba@suse.com>
+Signed-off-by: David Sterba <dsterba@suse.com>
+---
+ fs/btrfs/backref.c | 2 +-
+ fs/btrfs/delayed-ref.c | 5 +----
+ fs/btrfs/delayed-ref.h | 3 ++-
+ fs/btrfs/extent-tree.c | 6 +++---
+ 4 files changed, 7 insertions(+), 9 deletions(-)
+
+diff --git a/fs/btrfs/backref.c b/fs/btrfs/backref.c
+index 8299601a3549..db706595e631 100644
+--- a/fs/btrfs/backref.c
++++ b/fs/btrfs/backref.c
+@@ -1284,7 +1284,7 @@ static int find_parent_nodes(struct btrfs_trans_handle *trans,
+ */
+ delayed_refs = &trans->transaction->delayed_refs;
+ spin_lock(&delayed_refs->lock);
+- head = btrfs_find_delayed_ref_head(trans, bytenr);
++ head = btrfs_find_delayed_ref_head(delayed_refs, bytenr);
+ if (head) {
+ if (!mutex_trylock(&head->mutex)) {
+ atomic_inc(&head->node.refs);
+diff --git a/fs/btrfs/delayed-ref.c b/fs/btrfs/delayed-ref.c
+index c66f487b76a7..a1b9ef2dfc4a 100644
+--- a/fs/btrfs/delayed-ref.c
++++ b/fs/btrfs/delayed-ref.c
+@@ -909,11 +909,8 @@ int btrfs_add_delayed_extent_op(struct btrfs_fs_info *fs_info,
+ * the head node if any where found, or NULL if not.
+ */
+ struct btrfs_delayed_ref_head *
+-btrfs_find_delayed_ref_head(struct btrfs_trans_handle *trans, u64 bytenr)
++btrfs_find_delayed_ref_head(struct btrfs_delayed_ref_root *delayed_refs, u64 bytenr)
+ {
+- struct btrfs_delayed_ref_root *delayed_refs;
+-
+- delayed_refs = &trans->transaction->delayed_refs;
+ return find_ref_head(&delayed_refs->href_root, bytenr, 0);
+ }
+
+diff --git a/fs/btrfs/delayed-ref.h b/fs/btrfs/delayed-ref.h
+index 8a0220fb703c..0e537f98f1a1 100644
+--- a/fs/btrfs/delayed-ref.h
++++ b/fs/btrfs/delayed-ref.h
+@@ -261,7 +261,8 @@ void btrfs_merge_delayed_refs(struct btrfs_trans_handle *trans,
+ struct btrfs_delayed_ref_head *head);
+
+ struct btrfs_delayed_ref_head *
+-btrfs_find_delayed_ref_head(struct btrfs_trans_handle *trans, u64 bytenr);
++btrfs_find_delayed_ref_head(struct btrfs_delayed_ref_root *delayed_refs,
++ u64 bytenr);
+ int btrfs_delayed_ref_lock(struct btrfs_trans_handle *trans,
+ struct btrfs_delayed_ref_head *head);
+ static inline void btrfs_delayed_ref_unlock(struct btrfs_delayed_ref_head *head)
+diff --git a/fs/btrfs/extent-tree.c b/fs/btrfs/extent-tree.c
+index 7dd71fcc1051..be235b30a798 100644
+--- a/fs/btrfs/extent-tree.c
++++ b/fs/btrfs/extent-tree.c
+@@ -888,7 +888,7 @@ int btrfs_lookup_extent_info(struct btrfs_trans_handle *trans,
+
+ delayed_refs = &trans->transaction->delayed_refs;
+ spin_lock(&delayed_refs->lock);
+- head = btrfs_find_delayed_ref_head(trans, bytenr);
++ head = btrfs_find_delayed_ref_head(delayed_refs, bytenr);
+ if (head) {
+ if (!mutex_trylock(&head->mutex)) {
+ atomic_inc(&head->node.refs);
+@@ -3041,7 +3041,7 @@ static noinline int check_delayed_ref(struct btrfs_trans_handle *trans,
+
+ delayed_refs = &trans->transaction->delayed_refs;
+ spin_lock(&delayed_refs->lock);
+- head = btrfs_find_delayed_ref_head(trans, bytenr);
++ head = btrfs_find_delayed_ref_head(delayed_refs, bytenr);
+ if (!head) {
+ spin_unlock(&delayed_refs->lock);
+ return 0;
+@@ -7091,7 +7091,7 @@ static noinline int check_ref_cleanup(struct btrfs_trans_handle *trans,
+
+ delayed_refs = &trans->transaction->delayed_refs;
+ spin_lock(&delayed_refs->lock);
+- head = btrfs_find_delayed_ref_head(trans, bytenr);
++ head = btrfs_find_delayed_ref_head(delayed_refs, bytenr);
+ if (!head)
+ goto out_delayed_unlock;
+
+--
+2.19.1
+
diff --git a/patches.suse/0001-btrfs-qgroup-Add-quick-exit-for-non-fs-extents.patch b/patches.suse/0001-btrfs-qgroup-Add-quick-exit-for-non-fs-extents.patch
new file mode 100644
index 0000000000..1b1bd36608
--- /dev/null
+++ b/patches.suse/0001-btrfs-qgroup-Add-quick-exit-for-non-fs-extents.patch
@@ -0,0 +1,121 @@
+From 5edfd9fdc644bf426a8bf9192d9c1a3680d75862 Mon Sep 17 00:00:00 2001
+From: Qu Wenruo <quwenruo@cn.fujitsu.com>
+Date: Mon, 27 Feb 2017 15:10:34 +0800
+Patch-mainline: v4.13-rc1
+Git-commit: 5edfd9fdc644bf426a8bf9192d9c1a3680d75862
+References: dependency for bsc#1031392
+Subject: [PATCH 1/6] btrfs: qgroup: Add quick exit for non-fs extents
+
+Modify btrfs_qgroup_account_extent() to exit quicker for non-fs extents.
+
+The quick exit condition is:
+1) The extent belongs to a non-fs tree
+ Only fs-tree extents can affect qgroup numbers and is the only case
+ where extent can be shared between different trees.
+
+ Although strictly speaking extent in data-reloc or tree-reloc tree
+ can be shared, data/tree-reloc root won't appear in the result of
+ btrfs_find_all_roots(), so we can ignore such case.
+
+ So we can check the first root in old_roots/new_roots ulist.
+ - if we find the 1st root is a not a fs/subvol root, then we can skip
+ the extent
+ - if we find the 1st root is a fs/subvol root, then we must continue
+ calculation
+
+OR
+
+2) both 'nr_old_roots' and 'nr_new_roots' are 0
+ This means either such extent got allocated then freed in current
+ transaction or it's a new reloc tree extent, whose nr_new_roots is 0.
+ Either way it won't affect qgroup accounting and can be skipped
+ safely.
+
+Such quick exit can make trace output more quite and less confusing:
+(example with fs uuid and time stamp removed)
+
+Before:
+------
+add_delayed_tree_ref: bytenr=29556736 num_bytes=16384 action=ADD_DELAYED_REF parent=0(-) ref_root=2(EXTENT_TREE) level=0 type=TREE_BLOCK_REF seq=0
+btrfs_qgroup_account_extent: bytenr=29556736 num_bytes=16384 nr_old_roots=0 nr_new_roots=1
+------
+Extent tree block will trigger btrfs_qgroup_account_extent() trace point
+while no qgroup number is changed, as extent tree won't affect qgroup
+accounting.
+
+After:
+------
+add_delayed_tree_ref: bytenr=29556736 num_bytes=16384 action=ADD_DELAYED_REF parent=0(-) ref_root=2(EXTENT_TREE) level=0 type=TREE_BLOCK_REF seq=0
+------
+Now such unrelated extent won't trigger btrfs_qgroup_account_extent()
+trace point, making the trace less noisy.
+
+Signed-off-by: Qu Wenruo <quwenruo@cn.fujitsu.com>
+[ changelog and comment adjustments ]
+Signed-off-by: David Sterba <dsterba@suse.com>
+Signed-off-by: Qu Wenruo <wqu@suse.com>
+---
+ fs/btrfs/qgroup.c | 43 +++++++++++++++++++++++++++++++++++++++++--
+ 1 file changed, 41 insertions(+), 2 deletions(-)
+
+--- a/fs/btrfs/qgroup.c
++++ b/fs/btrfs/qgroup.c
+@@ -1890,6 +1890,35 @@ static int qgroup_update_counters(struct
+ return 0;
+ }
+
++/*
++ * Check if the @roots potentially is a list of fs tree roots
++ *
++ * Return 0 for definitely not a fs/subvol tree roots ulist
++ * Return 1 for possible fs/subvol tree roots in the list (considering an empty
++ * one as well)
++ */
++static int maybe_fs_roots(struct ulist *roots)
++{
++ struct ulist_node *unode;
++ struct ulist_iterator uiter;
++
++ /* Empty one, still possible for fs roots */
++ if (!roots || roots->nnodes == 0)
++ return 1;
++
++ ULIST_ITER_INIT(&uiter);
++ unode = ulist_next(roots, &uiter);
++ if (!unode)
++ return 1;
++
++ /*
++ * If it contains fs tree roots, then it must belong to fs/subvol
++ * trees.
++ * If it contains a non-fs tree, it won't be shared with fs/subvol trees.
++ */
++ return is_fstree(unode->val);
++}
++
+ int
+ btrfs_qgroup_account_extent(struct btrfs_trans_handle *trans,
+ struct btrfs_fs_info *fs_info,
+@@ -1903,10 +1932,20 @@ btrfs_qgroup_account_extent(struct btrfs
+ u64 nr_old_roots = 0;
+ int ret = 0;
+
+- if (new_roots)
++ if (new_roots) {
++ if (!maybe_fs_roots(new_roots))
++ goto out_free;
+ nr_new_roots = new_roots->nnodes;
+- if (old_roots)
++ }
++ if (old_roots) {
++ if (!maybe_fs_roots(old_roots))
++ goto out_free;
+ nr_old_roots = old_roots->nnodes;
++ }
++
++ /* Quick exit, either not fs tree roots, or won't affect any qgroup */
++ if (nr_old_roots == 0 && nr_new_roots == 0)
++ goto out_free;
+
+ if (!test_bit(BTRFS_FS_QUOTA_ENABLED, &fs_info->flags))
+ goto out_free;
diff --git a/patches.suse/0001-btrfs-qgroup-Add-trace-point-for-qgroup-reserved-spa.patch b/patches.suse/0001-btrfs-qgroup-Add-trace-point-for-qgroup-reserved-spa.patch
new file mode 100644
index 0000000000..728de67d8f
--- /dev/null
+++ b/patches.suse/0001-btrfs-qgroup-Add-trace-point-for-qgroup-reserved-spa.patch
@@ -0,0 +1,251 @@
+From 3159fe7baef3a50fc332455e252d8a01a18f1ff1 Mon Sep 17 00:00:00 2001
+From: Qu Wenruo <quwenruo@cn.fujitsu.com>
+Patch-mainline: v4.12
+Git-commit: 3159fe7baef3a50fc332455e252d8a01a18f1ff1
+References: dependency for bsc#1031392
+Date: Mon, 13 Mar 2017 15:52:08 +0800
+
+Subject: [PATCH] btrfs: qgroup: Add trace point for qgroup reserved space
+
+Introduce the following trace points:
+qgroup_update_reserve
+qgroup_meta_reserve
+
+These trace points are handy to trace qgroup reserve space related
+problems.
+
+Also export btrfs_qgroup structure, as now we directly pass btrfs_qgroup
+structure to trace points, so that structure needs to be exported.
+
+Signed-off-by: Qu Wenruo <quwenruo@cn.fujitsu.com>
+Reviewed-by: David Sterba <dsterba@suse.com>
+Signed-off-by: David Sterba <dsterba@suse.com>
+---
+ fs/btrfs/qgroup.c | 52 ++++++-------------------------------------
+ fs/btrfs/qgroup.h | 44 ++++++++++++++++++++++++++++++++++++
+ include/trace/events/btrfs.h | 44 ++++++++++++++++++++++++++++++++++++
+ 3 files changed, 96 insertions(+), 44 deletions(-)
+
+--- a/fs/btrfs/qgroup.c
++++ b/fs/btrfs/qgroup.c
+@@ -47,50 +47,6 @@
+ * - check all ioctl parameters
+ */
+
+-/*
+- * one struct for each qgroup, organized in fs_info->qgroup_tree.
+- */
+-struct btrfs_qgroup {
+- u64 qgroupid;
+-
+- /*
+- * state
+- */
+- u64 rfer; /* referenced */
+- u64 rfer_cmpr; /* referenced compressed */
+- u64 excl; /* exclusive */
+- u64 excl_cmpr; /* exclusive compressed */
+-
+- /*
+- * limits
+- */
+- u64 lim_flags; /* which limits are set */
+- u64 max_rfer;
+- u64 max_excl;
+- u64 rsv_rfer;
+- u64 rsv_excl;
+-
+- /*
+- * reservation tracking
+- */
+- u64 reserved;
+-
+- /*
+- * lists
+- */
+- struct list_head groups; /* groups this group is member of */
+- struct list_head members; /* groups that are members of this group */
+- struct list_head dirty; /* dirty groups */
+- struct rb_node node; /* tree of qgroups */
+-
+- /*
+- * temp variables for accounting operations
+- * Refer to qgroup_shared_accouting() for details.
+- */
+- u64 old_refcnt;
+- u64 new_refcnt;
+-};
+-
+ static void btrfs_qgroup_update_old_refcnt(struct btrfs_qgroup *qg, u64 seq,
+ int mod)
+ {
+@@ -1071,6 +1027,7 @@ static int __qgroup_excl_accounting(stru
+ qgroup->excl += sign * num_bytes;
+ qgroup->excl_cmpr += sign * num_bytes;
+ if (sign > 0) {
++ trace_qgroup_update_reserve(fs_info, qgroup, -(s64)num_bytes);
+ if (qgroup->reserved < num_bytes)
+ report_reserved_underflow(fs_info, qgroup, num_bytes);
+ else
+@@ -1096,6 +1053,8 @@ static int __qgroup_excl_accounting(stru
+ WARN_ON(sign < 0 && qgroup->excl < num_bytes);
+ qgroup->excl += sign * num_bytes;
+ if (sign > 0) {
++ trace_qgroup_update_reserve(fs_info, qgroup,
++ -(s64)num_bytes);
+ if (qgroup->reserved < num_bytes)
+ report_reserved_underflow(fs_info, qgroup,
+ num_bytes);
+@@ -2424,6 +2383,7 @@ retry:
+
+ qg = u64_to_ptr(unode->aux);
+
++ trace_qgroup_update_reserve(fs_info, qg, num_bytes);
+ qg->reserved += num_bytes;
+ }
+
+@@ -2469,6 +2429,7 @@ void btrfs_qgroup_free_refroot(struct bt
+
+ qg = u64_to_ptr(unode->aux);
+
++ trace_qgroup_update_reserve(fs_info, qg, -(s64)num_bytes);
+ if (qg->reserved < num_bytes)
+ report_reserved_underflow(fs_info, qg, num_bytes);
+ else
+@@ -3048,6 +3009,7 @@ int btrfs_qgroup_reserve_meta(struct btr
+ return 0;
+
+ BUG_ON(num_bytes != round_down(num_bytes, root->nodesize));
++ trace_qgroup_meta_reserve(root, (s64)num_bytes);
+ ret = qgroup_reserve(root, num_bytes, enforce);
+ if (ret < 0)
+ return ret;
+@@ -3066,6 +3028,7 @@ void btrfs_qgroup_free_meta_all(struct b
+ reserved = atomic64_xchg(&root->qgroup_meta_rsv, 0);
+ if (reserved == 0)
+ return;
++ trace_qgroup_meta_reserve(root, -(s64)reserved);
+ btrfs_qgroup_free_refroot(root->fs_info, root->objectid, reserved);
+ }
+
+@@ -3078,6 +3041,7 @@ void btrfs_qgroup_free_meta(struct btrfs
+ BUG_ON(num_bytes != round_down(num_bytes, root->nodesize));
+ WARN_ON(atomic64_read(&root->qgroup_meta_rsv) < num_bytes);
+ atomic64_sub(num_bytes, &root->qgroup_meta_rsv);
++ trace_qgroup_meta_reserve(root, -(s64)num_bytes);
+ btrfs_qgroup_free_refroot(root->fs_info, root->objectid, num_bytes);
+ }
+
+--- a/fs/btrfs/qgroup.h
++++ b/fs/btrfs/qgroup.h
+@@ -34,6 +34,50 @@ struct btrfs_qgroup_extent_record {
+ };
+
+ /*
++ * one struct for each qgroup, organized in fs_info->qgroup_tree.
++ */
++struct btrfs_qgroup {
++ u64 qgroupid;
++
++ /*
++ * state
++ */
++ u64 rfer; /* referenced */
++ u64 rfer_cmpr; /* referenced compressed */
++ u64 excl; /* exclusive */
++ u64 excl_cmpr; /* exclusive compressed */
++
++ /*
++ * limits
++ */
++ u64 lim_flags; /* which limits are set */
++ u64 max_rfer;
++ u64 max_excl;
++ u64 rsv_rfer;
++ u64 rsv_excl;
++
++ /*
++ * reservation tracking
++ */
++ u64 reserved;
++
++ /*
++ * lists
++ */
++ struct list_head groups; /* groups this group is member of */
++ struct list_head members; /* groups that are members of this group */
++ struct list_head dirty; /* dirty groups */
++ struct rb_node node; /* tree of qgroups */
++
++ /*
++ * temp variables for accounting operations
++ * Refer to qgroup_shared_accounting() for details.
++ */
++ u64 old_refcnt;
++ u64 new_refcnt;
++};
++
++/*
+ * For qgroup event trace points only
+ */
+ #define QGROUP_RESERVE (1<<0)
+--- a/include/trace/events/btrfs.h
++++ b/include/trace/events/btrfs.h
+@@ -25,6 +25,7 @@ struct btrfs_work;
+ struct __btrfs_workqueue;
+ struct btrfs_qgroup_extent_record;
+ struct prelim_ref;
++struct btrfs_qgroup;
+
+ #define show_ref_type(type) \
+ __print_symbolic(type, \
+@@ -1543,6 +1544,49 @@ DEFINE_EVENT(btrfs__prelim_ref, btrfs_pr
+ TP_ARGS(fs_info, oldref, newref, tree_size)
+ );
+
++TRACE_EVENT(qgroup_update_reserve,
++
++ TP_PROTO(struct btrfs_fs_info *fs_info, struct btrfs_qgroup *qgroup,
++ s64 diff),
++
++ TP_ARGS(fs_info, qgroup, diff),
++
++ TP_STRUCT__entry_btrfs(
++ __field( u64, qgid )
++ __field( u64, cur_reserved )
++ __field( s64, diff )
++ ),
++
++ TP_fast_assign_btrfs(fs_info,
++ __entry->qgid = qgroup->qgroupid;
++ __entry->cur_reserved = qgroup->reserved;
++ __entry->diff = diff;
++ ),
++
++ TP_printk_btrfs("qgid=%llu cur_reserved=%llu diff=%lld",
++ __entry->qgid, __entry->cur_reserved, __entry->diff)
++);
++
++TRACE_EVENT(qgroup_meta_reserve,
++
++ TP_PROTO(struct btrfs_root *root, s64 diff),
++
++ TP_ARGS(root, diff),
++
++ TP_STRUCT__entry_btrfs(
++ __field( u64, refroot )
++ __field( s64, diff )
++ ),
++
++ TP_fast_assign_btrfs(root->fs_info,
++ __entry->refroot = root->objectid;
++ __entry->diff = diff;
++ ),
++
++ TP_printk_btrfs("refroot=%llu(%s) diff=%lld",
++ show_root_type(__entry->refroot), __entry->diff)
++);
++
+ #endif /* _TRACE_BTRFS_H */
+
+ /* This part must be outside protection */
diff --git a/patches.suse/0002-Btrfs-kill-trans-in-run_delalloc_nocow-and-btrfs_cro.patch b/patches.suse/0002-Btrfs-kill-trans-in-run_delalloc_nocow-and-btrfs_cro.patch
new file mode 100644
index 0000000000..acbc3524bf
--- /dev/null
+++ b/patches.suse/0002-Btrfs-kill-trans-in-run_delalloc_nocow-and-btrfs_cro.patch
@@ -0,0 +1,190 @@
+From e4c3b2dcd1449def1229efb138da7cb28c796c71 Mon Sep 17 00:00:00 2001
+From: Liu Bo <bo.li.liu@oracle.com>
+Date: Mon, 30 Jan 2017 12:25:28 -0800
+Patch-mainline: v4.11
+Git-commit: e4c3b2dcd1449def1229efb138da7cb28c796c71
+References: dependency for bsc#1031392
+Subject: [PATCH 2/2] Btrfs: kill trans in run_delalloc_nocow and
+ btrfs_cross_ref_exist
+
+run_delalloc_nocow has used trans in two places where they don't
+actually need @trans.
+
+For btrfs_lookup_file_extent, we search for file extents without COWing
+anything, and for btrfs_cross_ref_exist, the only place where we need
+@trans is deferencing it in order to get running_transaction which we
+could easily get from the global fs_info.
+
+Signed-off-by: Liu Bo <bo.li.liu@oracle.com>
+Reviewed-by: David Sterba <dsterba@suse.com>
+Signed-off-by: David Sterba <dsterba@suse.com>
+---
+ fs/btrfs/ctree.h | 3 +--
+ fs/btrfs/extent-tree.c | 22 ++++++++++++----------
+ fs/btrfs/inode.c | 39 +++------------------------------------
+ 3 files changed, 16 insertions(+), 48 deletions(-)
+
+--- a/fs/btrfs/ctree.h
++++ b/fs/btrfs/ctree.h
+@@ -2570,8 +2570,7 @@ int btrfs_pin_extent_for_log_replay(stru
+ u64 bytenr, u64 num_bytes);
+ int btrfs_exclude_logged_extents(struct btrfs_root *root,
+ struct extent_buffer *eb);
+-int btrfs_cross_ref_exist(struct btrfs_trans_handle *trans,
+- struct btrfs_root *root,
++int btrfs_cross_ref_exist(struct btrfs_root *root,
+ u64 objectid, u64 offset, u64 bytenr);
+ struct btrfs_block_group_cache *btrfs_lookup_block_group(
+ struct btrfs_fs_info *info,
+--- a/fs/btrfs/extent-tree.c
++++ b/fs/btrfs/extent-tree.c
+@@ -3074,8 +3074,7 @@ int btrfs_set_disk_extent_flags(struct b
+ return ret;
+ }
+
+-static noinline int check_delayed_ref(struct btrfs_trans_handle *trans,
+- struct btrfs_root *root,
++static noinline int check_delayed_ref(struct btrfs_root *root,
+ struct btrfs_path *path,
+ u64 objectid, u64 offset, u64 bytenr)
+ {
+@@ -3083,9 +3082,14 @@ static noinline int check_delayed_ref(st
+ struct btrfs_delayed_ref_node *ref;
+ struct btrfs_delayed_data_ref *data_ref;
+ struct btrfs_delayed_ref_root *delayed_refs;
++ struct btrfs_transaction *cur_trans;
+ int ret = 0;
+
+- delayed_refs = &trans->transaction->delayed_refs;
++ cur_trans = root->fs_info->running_transaction;
++ if (!cur_trans)
++ return 0;
++
++ delayed_refs = &cur_trans->delayed_refs;
+ spin_lock(&delayed_refs->lock);
+ head = btrfs_find_delayed_ref_head(delayed_refs, bytenr);
+ if (!head) {
+@@ -3136,8 +3140,7 @@ static noinline int check_delayed_ref(st
+ return ret;
+ }
+
+-static noinline int check_committed_ref(struct btrfs_trans_handle *trans,
+- struct btrfs_root *root,
++static noinline int check_committed_ref(struct btrfs_root *root,
+ struct btrfs_path *path,
+ u64 objectid, u64 offset, u64 bytenr)
+ {
+@@ -3207,9 +3210,8 @@ out:
+ return ret;
+ }
+
+-int btrfs_cross_ref_exist(struct btrfs_trans_handle *trans,
+- struct btrfs_root *root,
+- u64 objectid, u64 offset, u64 bytenr)
++int btrfs_cross_ref_exist(struct btrfs_root *root, u64 objectid, u64 offset,
++ u64 bytenr)
+ {
+ struct btrfs_path *path;
+ int ret;
+@@ -3220,12 +3222,12 @@ int btrfs_cross_ref_exist(struct btrfs_t
+ return -ENOENT;
+
+ do {
+- ret = check_committed_ref(trans, root, path, objectid,
++ ret = check_committed_ref(root, path, objectid,
+ offset, bytenr);
+ if (ret && ret != -ENOENT)
+ goto out;
+
+- ret2 = check_delayed_ref(trans, root, path, objectid,
++ ret2 = check_delayed_ref(root, path, objectid,
+ offset, bytenr);
+ } while (ret2 == -EAGAIN);
+
+--- a/fs/btrfs/inode.c
++++ b/fs/btrfs/inode.c
+@@ -1247,7 +1247,6 @@ static noinline int run_delalloc_nocow(s
+ unsigned long *nr_written)
+ {
+ struct btrfs_root *root = BTRFS_I(inode)->root;
+- struct btrfs_trans_handle *trans;
+ struct extent_buffer *leaf;
+ struct btrfs_path *path;
+ struct btrfs_file_extent_item *fi;
+@@ -1283,30 +1282,10 @@ static noinline int run_delalloc_nocow(s
+
+ nolock = btrfs_is_free_space_inode(inode);
+
+- if (nolock)
+- trans = btrfs_join_transaction_nolock(root);
+- else
+- trans = btrfs_join_transaction(root);
+-
+- if (IS_ERR(trans)) {
+- extent_clear_unlock_delalloc(inode, start, end, end,
+- locked_page,
+- EXTENT_LOCKED | EXTENT_DELALLOC |
+- EXTENT_DO_ACCOUNTING |
+- EXTENT_DEFRAG, PAGE_UNLOCK |
+- PAGE_CLEAR_DIRTY |
+- PAGE_SET_WRITEBACK |
+- PAGE_END_WRITEBACK);
+- btrfs_free_path(path);
+- return PTR_ERR(trans);
+- }
+-
+- trans->block_rsv = &root->fs_info->delalloc_block_rsv;
+-
+ cow_start = (u64)-1;
+ cur_offset = start;
+ while (1) {
+- ret = btrfs_lookup_file_extent(trans, root, path, ino,
++ ret = btrfs_lookup_file_extent(NULL, root, path, ino,
+ cur_offset, 0);
+ if (ret < 0)
+ goto error;
+@@ -1382,7 +1361,7 @@ next_slot:
+ goto out_check;
+ if (btrfs_extent_readonly(root, disk_bytenr))
+ goto out_check;
+- ret = btrfs_cross_ref_exist(trans, root, ino,
++ ret = btrfs_cross_ref_exist(root, ino,
+ found_key.offset -
+ extent_offset, disk_bytenr);
+ if (ret) {
+@@ -1559,10 +1538,6 @@ out_check:
+ }
+
+ error:
+- err = btrfs_end_transaction(trans, root);
+- if (!ret)
+- ret = err;
+-
+ if (ret && cur_offset < end)
+ extent_clear_unlock_delalloc(inode, cur_offset, end, end,
+ locked_page, EXTENT_LOCKED |
+@@ -7320,7 +7295,6 @@ noinline int can_nocow_extent(struct ino
+ u64 *orig_start, u64 *orig_block_len,
+ u64 *ram_bytes)
+ {
+- struct btrfs_trans_handle *trans;
+ struct btrfs_path *path;
+ int ret;
+ struct extent_buffer *leaf;
+@@ -7422,15 +7396,8 @@ noinline int can_nocow_extent(struct ino
+ * look for other files referencing this extent, if we
+ * find any we must cow
+ */
+- trans = btrfs_join_transaction(root);
+- if (IS_ERR(trans)) {
+- ret = 0;
+- goto out;
+- }
+-
+- ret = btrfs_cross_ref_exist(trans, root, btrfs_ino(inode),
++ ret = btrfs_cross_ref_exist(root, btrfs_ino(inode),
+ key.offset - backref_offset, disk_bytenr);
+- btrfs_end_transaction(trans, root);
+ if (ret) {
+ ret = 0;
+ goto out;
diff --git a/patches.suse/0002-btrfs-qgroup-Cleanup-btrfs_qgroup_prepare_account_ex.patch b/patches.suse/0002-btrfs-qgroup-Cleanup-btrfs_qgroup_prepare_account_ex.patch
new file mode 100644
index 0000000000..e4659203cb
--- /dev/null
+++ b/patches.suse/0002-btrfs-qgroup-Cleanup-btrfs_qgroup_prepare_account_ex.patch
@@ -0,0 +1,139 @@
+From d1b8b94a2b4f416b416bdfde46315e9aef17f358 Mon Sep 17 00:00:00 2001
+From: Qu Wenruo <quwenruo@cn.fujitsu.com>
+Date: Mon, 27 Feb 2017 15:10:35 +0800
+Patch-mainline: v4.13-rc1
+Git-commit: d1b8b94a2b4f416b416bdfde46315e9aef17f358
+References: dependency for bsc#1031392
+Subject: [PATCH 2/6] btrfs: qgroup: Cleanup
+ btrfs_qgroup_prepare_account_extents function
+
+Quite a lot of qgroup corruption happens due to wrong time of calling
+btrfs_qgroup_prepare_account_extents().
+
+Since the safest time is to call it just before
+btrfs_qgroup_account_extents(), there is no need to separate these 2
+functions.
+
+Merging them will make code cleaner and less bug prone.
+
+Signed-off-by: Qu Wenruo <quwenruo@cn.fujitsu.com>
+[ changelog and comment adjustments ]
+Signed-off-by: David Sterba <dsterba@suse.com>
+Signed-off-by: Qu Wenruo <wqu@suse.com>
+---
+ fs/btrfs/qgroup.c | 49 +++++++++++++++++--------------------------------
+ fs/btrfs/qgroup.h | 3 +--
+ fs/btrfs/transaction.c | 10 ----------
+ 3 files changed, 18 insertions(+), 44 deletions(-)
+
+--- a/fs/btrfs/qgroup.c
++++ b/fs/btrfs/qgroup.c
+@@ -1399,37 +1399,6 @@ out:
+ return ret;
+ }
+
+-int btrfs_qgroup_prepare_account_extents(struct btrfs_trans_handle *trans,
+- struct btrfs_fs_info *fs_info)
+-{
+- struct btrfs_qgroup_extent_record *record;
+- struct btrfs_delayed_ref_root *delayed_refs;
+- struct rb_node *node;
+- u64 qgroup_to_skip;
+- int ret = 0;
+-
+- delayed_refs = &trans->transaction->delayed_refs;
+- qgroup_to_skip = delayed_refs->qgroup_to_skip;
+-
+- /*
+- * No need to do lock, since this function will only be called in
+- * btrfs_commmit_transaction().
+- */
+- node = rb_first(&delayed_refs->dirty_extent_root);
+- while (node) {
+- record = rb_entry(node, struct btrfs_qgroup_extent_record,
+- node);
+- ret = btrfs_find_all_roots(NULL, fs_info, record->bytenr, 0,
+- &record->old_roots);
+- if (ret < 0)
+- break;
+- if (qgroup_to_skip)
+- ulist_del(record->old_roots, qgroup_to_skip, 0);
+- node = rb_next(node);
+- }
+- return ret;
+-}
+-
+ int btrfs_qgroup_trace_extent_nolock(struct btrfs_fs_info *fs_info,
+ struct btrfs_delayed_ref_root *delayed_refs,
+ struct btrfs_qgroup_extent_record *record)
+@@ -2026,6 +1995,19 @@ int btrfs_qgroup_account_extents(struct
+ trace_btrfs_qgroup_account_extents(fs_info, record);
+
+ if (!ret) {
++ /*
++ * Old roots should be searched when inserting qgroup
++ * extent record
++ */
++ if (!record->old_roots) {
++ /* Search commit root to find old_roots */
++ ret = btrfs_find_all_roots(NULL, fs_info,
++ record->bytenr, 0,
++ &record->old_roots);
++ if (ret < 0)
++ goto cleanup;
++ }
++
+ /*
+ * Use (u64)-1 as time_seq to do special search, which
+ * doesn't lock tree or delayed_refs and search current
+@@ -2035,8 +2017,11 @@ int btrfs_qgroup_account_extents(struct
+ record->bytenr, (u64)-1, &new_roots);
+ if (ret < 0)
+ goto cleanup;
+- if (qgroup_to_skip)
++ if (qgroup_to_skip) {
+ ulist_del(new_roots, qgroup_to_skip, 0);
++ ulist_del(record->old_roots, qgroup_to_skip,
++ 0);
++ }
+ ret = btrfs_qgroup_account_extent(trans, fs_info,
+ record->bytenr, record->num_bytes,
+ record->old_roots, new_roots);
+--- a/fs/btrfs/qgroup.h
++++ b/fs/btrfs/qgroup.h
+@@ -106,8 +106,7 @@ int btrfs_limit_qgroup(struct btrfs_tran
+ int btrfs_read_qgroup_config(struct btrfs_fs_info *fs_info);
+ void btrfs_free_qgroup_config(struct btrfs_fs_info *fs_info);
+ struct btrfs_delayed_extent_op;
+-int btrfs_qgroup_prepare_account_extents(struct btrfs_trans_handle *trans,
+- struct btrfs_fs_info *fs_info);
++
+ /*
+ * Inform qgroup to trace one dirty extent, its info is recorded in @record.
+ * So qgroup can account it at commit trans time.
+--- a/fs/btrfs/transaction.c
++++ b/fs/btrfs/transaction.c
+@@ -1351,9 +1351,6 @@ static int qgroup_account_snapshot(struc
+ ret = commit_fs_roots(trans, src);
+ if (ret)
+ goto out;
+- ret = btrfs_qgroup_prepare_account_extents(trans, fs_info);
+- if (ret < 0)
+- goto out;
+ ret = btrfs_qgroup_account_extents(trans, fs_info);
+ if (ret < 0)
+ goto out;
+@@ -2102,13 +2099,6 @@ int btrfs_commit_transaction(struct btrf
+ if (ret) {
+ mutex_unlock(&root->fs_info->reloc_mutex);
+ goto scrub_continue;
+- }
+-
+- /* Reocrd old roots for later qgroup accounting */
+- ret = btrfs_qgroup_prepare_account_extents(trans, root->fs_info);
+- if (ret) {
+- mutex_unlock(&root->fs_info->reloc_mutex);
+- goto scrub_continue;
+ }
+
+ /*
diff --git a/patches.suse/0007-btrfs-qgroup-Skeleton-to-support-separate-qgroup-res.patch b/patches.suse/0007-btrfs-qgroup-Skeleton-to-support-separate-qgroup-res.patch
new file mode 100644
index 0000000000..40b77ef038
--- /dev/null
+++ b/patches.suse/0007-btrfs-qgroup-Skeleton-to-support-separate-qgroup-res.patch
@@ -0,0 +1,150 @@
+From d4e5c92055d8933e9a2030fcbe6d0dbbec538c58 Mon Sep 17 00:00:00 2001
+From: Qu Wenruo <wqu@suse.com>
+Date: Tue, 12 Dec 2017 15:34:23 +0800
+Patch-mainline: v4.17-rc1
+Git-commit: d4e5c92055d8933e9a2030fcbe6d0dbbec538c58
+References: bsc#1031392
+Subject: [PATCH 07/16] btrfs: qgroup: Skeleton to support separate qgroup
+ reservation type
+
+Instead of single qgroup->reserved, use a new structure btrfs_qgroup_rsv
+to store different types of reservation.
+
+This patch only updates the header needed to compile.
+
+Signed-off-by: Qu Wenruo <wqu@suse.com>
+Signed-off-by: David Sterba <dsterba@suse.com>
+---
+ fs/btrfs/qgroup.c | 22 +++++++++++-----------
+ fs/btrfs/qgroup.h | 27 +++++++++++++++++++++++++--
+ 2 files changed, 36 insertions(+), 13 deletions(-)
+
+--- a/fs/btrfs/qgroup.c
++++ b/fs/btrfs/qgroup.c
+@@ -2417,7 +2417,8 @@ out:
+ }
+
+ void btrfs_qgroup_free_refroot(struct btrfs_fs_info *fs_info,
+- u64 ref_root, u64 num_bytes)
++ u64 ref_root, u64 num_bytes,
++ enum btrfs_qgroup_rsv_type type)
+ {
+ struct btrfs_root *quota_root;
+ struct btrfs_qgroup *qgroup;
+@@ -2942,7 +2943,8 @@ static int qgroup_free_reserved_data(str
+ goto out;
+ freed += changeset.bytes_changed;
+ }
+- btrfs_qgroup_free_refroot(root->fs_info, root->objectid, freed);
++ btrfs_qgroup_free_refroot(root->fs_info, root->objectid, freed,
++ BTRFS_QGROUP_RSV_DATA);
+ ret = freed;
+ out:
+ extent_changeset_release(&changeset);
+@@ -2967,18 +2969,14 @@ static int __btrfs_qgroup_release_data(s
+ if (ret < 0)
+ goto out;
+
+- if (free) {
+- btrfs_qgroup_free_refroot(BTRFS_I(inode)->root->fs_info,
+- BTRFS_I(inode)->root->objectid,
+- changeset.bytes_changed);
++ if (free)
+ trace_op = QGROUP_FREE;
+- }
+ trace_btrfs_qgroup_release_data(inode, start, len,
+ changeset.bytes_changed, trace_op);
+ if (free)
+ btrfs_qgroup_free_refroot(BTRFS_I(inode)->root->fs_info,
+ BTRFS_I(inode)->root->objectid,
+- changeset.bytes_changed);
++ changeset.bytes_changed, BTRFS_QGROUP_RSV_DATA);
+ ret = changeset.bytes_changed;
+ out:
+ extent_changeset_release(&changeset);
+@@ -3053,7 +3051,8 @@ void btrfs_qgroup_free_meta_all(struct b
+ if (reserved == 0)
+ return;
+ trace_qgroup_meta_reserve(root, -(s64)reserved);
+- btrfs_qgroup_free_refroot(root->fs_info, root->objectid, reserved);
++ btrfs_qgroup_free_refroot(root->fs_info, root->objectid, reserved,
++ BTRFS_QGROUP_RSV_META);
+ }
+
+ void btrfs_qgroup_free_meta(struct btrfs_root *root, int num_bytes)
+@@ -3066,7 +3065,8 @@ void btrfs_qgroup_free_meta(struct btrfs
+ WARN_ON(atomic64_read(&root->qgroup_meta_rsv) < num_bytes);
+ atomic64_sub(num_bytes, &root->qgroup_meta_rsv);
+ trace_qgroup_meta_reserve(root, -(s64)num_bytes);
+- btrfs_qgroup_free_refroot(root->fs_info, root->objectid, num_bytes);
++ btrfs_qgroup_free_refroot(root->fs_info, root->objectid, num_bytes,
++ BTRFS_QGROUP_RSV_META);
+ }
+
+ /*
+@@ -3094,7 +3094,7 @@ void btrfs_qgroup_check_reserved_leak(st
+ }
+ btrfs_qgroup_free_refroot(BTRFS_I(inode)->root->fs_info,
+ BTRFS_I(inode)->root->objectid,
+- changeset.bytes_changed);
++ changeset.bytes_changed, BTRFS_QGROUP_RSV_DATA);
+
+ }
+ extent_changeset_release(&changeset);
+--- a/fs/btrfs/qgroup.h
++++ b/fs/btrfs/qgroup.h
+@@ -33,6 +33,26 @@ struct btrfs_qgroup_extent_record {
+ struct ulist *old_roots;
+ };
+
++enum btrfs_qgroup_rsv_type {
++ BTRFS_QGROUP_RSV_DATA = 0,
++ BTRFS_QGROUP_RSV_META,
++ BTRFS_QGROUP_RSV_LAST,
++};
++
++/*
++ * Represents how many bytes we have reserved for this qgroup.
++ *
++ * Each type should have different reservation behavior.
++ * E.g, data follows its io_tree flag modification, while
++ * *currently* meta is just reserve-and-clear during transcation.
++ *
++ * TODO: Add new type for reservation which can survive transaction commit.
++ * Currect metadata reservation behavior is not suitable for such case.
++ */
++struct btrfs_qgroup_rsv {
++ u64 values[BTRFS_QGROUP_RSV_LAST];
++};
++
+ /*
+ * one struct for each qgroup, organized in fs_info->qgroup_tree.
+ */
+@@ -60,6 +80,7 @@ struct btrfs_qgroup {
+ * reservation tracking
+ */
+ u64 reserved;
++ struct btrfs_qgroup_rsv rsv;
+
+ /*
+ * lists
+@@ -173,7 +194,8 @@ int btrfs_qgroup_inherit(struct btrfs_tr
+ struct btrfs_fs_info *fs_info, u64 srcid, u64 objectid,
+ struct btrfs_qgroup_inherit *inherit);
+ void btrfs_qgroup_free_refroot(struct btrfs_fs_info *fs_info,
+- u64 ref_root, u64 num_bytes);
++ u64 ref_root, u64 num_bytes,
++ enum btrfs_qgroup_rsv_type type);
+ /*
+ * TODO: Add proper trace point for it, as btrfs_qgroup_free() is
+ * called by everywhere, can't provide good trace for delayed ref case.
+@@ -181,7 +203,8 @@ void btrfs_qgroup_free_refroot(struct bt
+ static inline void btrfs_qgroup_free_delayed_ref(struct btrfs_fs_info *fs_info,
+ u64 ref_root, u64 num_bytes)
+ {
+- btrfs_qgroup_free_refroot(fs_info, ref_root, num_bytes);
++ btrfs_qgroup_free_refroot(fs_info, ref_root, num_bytes,
++ BTRFS_QGROUP_RSV_DATA);
+ trace_btrfs_qgroup_free_delayed_ref(fs_info, ref_root, num_bytes);
+ }
+ void assert_qgroups_uptodate(struct btrfs_trans_handle *trans);
diff --git a/patches.suse/0008-btrfs-qgroup-Introduce-helpers-to-update-and-access-.patch b/patches.suse/0008-btrfs-qgroup-Introduce-helpers-to-update-and-access-.patch
new file mode 100644
index 0000000000..20632c177c
--- /dev/null
+++ b/patches.suse/0008-btrfs-qgroup-Introduce-helpers-to-update-and-access-.patch
@@ -0,0 +1,105 @@
+From f59c0347d4be22dad5812b5b14bf94ac0efd371a Mon Sep 17 00:00:00 2001
+From: Qu Wenruo <wqu@suse.com>
+Date: Tue, 12 Dec 2017 15:34:24 +0800
+Patch-mainline: v4.17-rc1
+Git-commit: f59c0347d4be22dad5812b5b14bf94ac0efd371a
+References: bsc#1031392
+Subject: [PATCH 08/16] btrfs: qgroup: Introduce helpers to update and access
+ new qgroup rsv
+
+Introduce helpers to:
+
+1) Get total reserved space
+ For limit calculation
+2) Add/release reserved space for given type
+ With underflow detection and warning
+3) Add/release reserved space according to child qgroup
+
+Signed-off-by: Qu Wenruo <wqu@suse.com>
+Signed-off-by: David Sterba <dsterba@suse.com>
+---
+ fs/btrfs/qgroup.c | 68 +++++++++++++++++++++++++++++++++++++++++++++++
+ 1 file changed, 68 insertions(+)
+
+diff --git a/fs/btrfs/qgroup.c b/fs/btrfs/qgroup.c
+index d6ab07f40f82..252af87340cc 100644
+--- a/fs/btrfs/qgroup.c
++++ b/fs/btrfs/qgroup.c
+@@ -47,6 +47,74 @@
+ * - check all ioctl parameters
+ */
+
++/*
++ * Helpers to access qgroup reservation
++ *
++ * Callers should ensure the lock context and type are valid
++ */
++
++static u64 qgroup_rsv_total(const struct btrfs_qgroup *qgroup)
++{
++ u64 ret = 0;
++ int i;
++
++ for (i = 0; i < BTRFS_QGROUP_RSV_LAST; i++)
++ ret += qgroup->rsv.values[i];
++
++ return ret;
++}
++
++#ifdef CONFIG_BTRFS_DEBUG
++static const char *qgroup_rsv_type_str(enum btrfs_qgroup_rsv_type type)
++{
++ if (type == BTRFS_QGROUP_RSV_DATA)
++ return "data";
++ if (type == BTRFS_QGROUP_RSV_META)
++ return "meta";
++ return NULL;
++}
++#endif
++
++static void qgroup_rsv_add(struct btrfs_qgroup *qgroup, u64 num_bytes,
++ enum btrfs_qgroup_rsv_type type)
++{
++ qgroup->rsv.values[type] += num_bytes;
++}
++
++static void qgroup_rsv_release(struct btrfs_qgroup *qgroup, u64 num_bytes,
++ enum btrfs_qgroup_rsv_type type)
++{
++ if (qgroup->rsv.values[type] >= num_bytes) {
++ qgroup->rsv.values[type] -= num_bytes;
++ return;
++ }
++#ifdef CONFIG_BTRFS_DEBUG
++ WARN_RATELIMIT(1,
++ "qgroup %llu %s reserved space underflow, have %llu to free %llu",
++ qgroup->qgroupid, qgroup_rsv_type_str(type),
++ qgroup->rsv.values[type], num_bytes);
++#endif
++ qgroup->rsv.values[type] = 0;
++}
++
++static void qgroup_rsv_add_by_qgroup(struct btrfs_qgroup *dest,
++ struct btrfs_qgroup *src)
++{
++ int i;
++
++ for (i = 0; i < BTRFS_QGROUP_RSV_LAST; i++)
++ qgroup_rsv_add(dest, src->rsv.values[i], i);
++}
++
++static void qgroup_rsv_release_by_qgroup(struct btrfs_qgroup *dest,
++ struct btrfs_qgroup *src)
++{
++ int i;
++
++ for (i = 0; i < BTRFS_QGROUP_RSV_LAST; i++)
++ qgroup_rsv_release(dest, src->rsv.values[i], i);
++}
++
+ static void btrfs_qgroup_update_old_refcnt(struct btrfs_qgroup *qg, u64 seq,
+ int mod)
+ {
+--
+2.19.0
+
diff --git a/patches.suse/0009-btrfs-qgroup-Make-qgroup_reserve-and-its-callers-to-.patch b/patches.suse/0009-btrfs-qgroup-Make-qgroup_reserve-and-its-callers-to-.patch
new file mode 100644
index 0000000000..2db45c406d
--- /dev/null
+++ b/patches.suse/0009-btrfs-qgroup-Make-qgroup_reserve-and-its-callers-to-.patch
@@ -0,0 +1,91 @@
+From dba213242fbcfc5495004ab76ca27c35ce1bf304 Mon Sep 17 00:00:00 2001
+From: Qu Wenruo <wqu@suse.com>
+Date: Tue, 12 Dec 2017 15:34:25 +0800
+Patch-mainline: v4.17-rc1
+Git-commit: dba213242fbcfc5495004ab76ca27c35ce1bf304
+References: bsc#1031392
+Subject: [PATCH 09/16] btrfs: qgroup: Make qgroup_reserve and its callers to
+ use separate reservation type
+
+Since most callers of qgroup_reserve() are already defined by type,
+converting qgroup_reserve() is quite an easy work.
+
+Signed-off-by: Qu Wenruo <wqu@suse.com>
+Signed-off-by: David Sterba <dsterba@suse.com>
+---
+ fs/btrfs/qgroup.c | 21 +++++++++------------
+ 1 file changed, 9 insertions(+), 12 deletions(-)
+
+--- a/fs/btrfs/qgroup.c
++++ b/fs/btrfs/qgroup.c
+@@ -2378,18 +2378,18 @@ out:
+ static bool qgroup_check_limits(const struct btrfs_qgroup *qg, u64 num_bytes)
+ {
+ if ((qg->lim_flags & BTRFS_QGROUP_LIMIT_MAX_RFER) &&
+- qg->reserved + (s64)qg->rfer + num_bytes > qg->max_rfer)
++ qgroup_rsv_total(qg) + (s64)qg->rfer + num_bytes > qg->max_rfer)
+ return false;
+
+ if ((qg->lim_flags & BTRFS_QGROUP_LIMIT_MAX_EXCL) &&
+- qg->reserved + (s64)qg->excl + num_bytes > qg->max_excl)
++ qgroup_rsv_total(qg) + (s64)qg->excl + num_bytes > qg->max_excl)
+ return false;
+
+ return true;
+ }
+
+-
+-static int qgroup_reserve(struct btrfs_root *root, u64 num_bytes, bool enforce)
++static int qgroup_reserve(struct btrfs_root *root, u64 num_bytes, bool enforce,
++ enum btrfs_qgroup_rsv_type type)
+ {
+ struct btrfs_root *quota_root;
+ struct btrfs_qgroup *qgroup;
+@@ -2436,7 +2436,7 @@ retry:
+ * Commit the tree and retry, since we may have
+ * deletions which would free up space.
+ */
+- if (!retried && qg->reserved > 0) {
++ if (!retried && qgroup_rsv_total(qg) > 0) {
+ struct btrfs_trans_handle *trans;
+
+ spin_unlock(&fs_info->qgroup_lock);
+@@ -2476,7 +2476,7 @@ retry:
+ qg = u64_to_ptr(unode->aux);
+
+ trace_qgroup_update_reserve(fs_info, qg, num_bytes);
+- qg->reserved += num_bytes;
++ qgroup_rsv_add(qg, num_bytes, type);
+ }
+
+ out:
+@@ -2523,10 +2523,7 @@ void btrfs_qgroup_free_refroot(struct bt
+ qg = u64_to_ptr(unode->aux);
+
+ trace_qgroup_update_reserve(fs_info, qg, -(s64)num_bytes);
+- if (qg->reserved < num_bytes)
+- report_reserved_underflow(fs_info, qg, num_bytes);
+- else
+- qg->reserved -= num_bytes;
++ qgroup_rsv_release(qg, num_bytes, type);
+
+ list_for_each_entry(glist, &qg->groups, next_group) {
+ ret = ulist_add(fs_info->qgroup_ulist,
+@@ -2947,7 +2944,7 @@ int btrfs_qgroup_reserve_data(struct ino
+ to_reserve, QGROUP_RESERVE);
+ if (ret < 0)
+ goto cleanup;
+- ret = qgroup_reserve(root, to_reserve, true);
++ ret = qgroup_reserve(root, to_reserve, true, BTRFS_QGROUP_RSV_DATA);
+ if (ret < 0)
+ goto cleanup;
+
+@@ -3100,7 +3097,7 @@ int btrfs_qgroup_reserve_meta(struct btr
+
+ BUG_ON(num_bytes != round_down(num_bytes, root->nodesize));
+ trace_qgroup_meta_reserve(root, (s64)num_bytes);
+- ret = qgroup_reserve(root, num_bytes, enforce);
++ ret = qgroup_reserve(root, num_bytes, enforce, BTRFS_QGROUP_RSV_META);
+ if (ret < 0)
+ return ret;
+ atomic64_add(num_bytes, &root->qgroup_meta_rsv);
diff --git a/patches.suse/0010-btrfs-qgroup-Fix-wrong-qgroup-reservation-update-for.patch b/patches.suse/0010-btrfs-qgroup-Fix-wrong-qgroup-reservation-update-for.patch
new file mode 100644
index 0000000000..9f1b1b741f
--- /dev/null
+++ b/patches.suse/0010-btrfs-qgroup-Fix-wrong-qgroup-reservation-update-for.patch
@@ -0,0 +1,132 @@
+From 429d6275d50199dd4c3a5876754003ae06c7f927 Mon Sep 17 00:00:00 2001
+From: Qu Wenruo <wqu@suse.com>
+Date: Tue, 12 Dec 2017 15:34:26 +0800
+Patch-mainline: v4.17-rc1
+Git-commit: 429d6275d50199dd4c3a5876754003ae06c7f927
+References: bsc#1031392
+Subject: [PATCH 10/16] btrfs: qgroup: Fix wrong qgroup reservation update for
+ relationship modification
+
+When modifying qgroup relationship, for qgroup which only owns exclusive
+extents, we will go through quick update path.
+
+In this path, we will add/subtract exclusive and reference number for
+parent qgroup, since the source (child) qgroup only has exclusive
+extents, destination (parent) qgroup will also own or lose those extents
+exclusively.
+
+The same should be the same for reservation, since later reservation
+adding/releasing will also affect parent qgroup, without the reservation
+carried from child, parent will underflow reservation or have dead
+reservation which will never be freed.
+
+However original code doesn't do the same thing for reservation.
+It handles qgroup reservation quite differently:
+
+It removes qgroup reservation, as it's allocating space from the
+reserved qgroup for relationship adding.
+But does nothing for qgroup reservation if we're removing a qgroup
+relationship.
+
+According to the original code, it looks just like because we're adding
+qgroup->rfer, the code assumes we're writing new data, so it's follows
+the normal write routine, by reducing qgroup->reserved and adding
+qgroup->rfer/excl.
+
+This old behavior is wrong, and should be fixed to follow the same
+excl/rfer behavior.
+
+Just fix it by using the correct behavior described above.
+
+Fixes: 31193213f1f9 ("Btrfs: qgroup: Introduce a may_use to account space_info->bytes_may_use.")
+Signed-off-by: Qu Wenruo <wqu@suse.com>
+Signed-off-by: David Sterba <dsterba@suse.com>
+---
+ fs/btrfs/qgroup.c | 44 +++++++++++++++++++++++---------------------
+ 1 file changed, 23 insertions(+), 21 deletions(-)
+
+--- a/fs/btrfs/qgroup.c
++++ b/fs/btrfs/qgroup.c
+@@ -1067,21 +1067,30 @@ static void report_reserved_underflow(st
+ #endif
+ qgroup->reserved = 0;
+ }
++
+ /*
+- * The easy accounting, if we are adding/removing the only ref for an extent
+- * then this qgroup and all of the parent qgroups get their refrence and
+- * exclusive counts adjusted.
++ * The easy accounting, we're updating qgroup relationship whose child qgroup
++ * only has exclusive extents.
++ *
++ * In this case, all exclsuive extents will also be exlusive for parent, so
++ * excl/rfer just get added/removed.
++ *
++ * So is qgroup reservation space, which should also be added/removed to
++ * parent.
++ * Or when child tries to release reservation space, parent will underflow its
++ * reservation (for relationship adding case).
+ *
+ * Caller should hold fs_info->qgroup_lock.
+ */
+ static int __qgroup_excl_accounting(struct btrfs_fs_info *fs_info,
+ struct ulist *tmp, u64 ref_root,
+- u64 num_bytes, int sign)
++ struct btrfs_qgroup *src, int sign)
+ {
+ struct btrfs_qgroup *qgroup;
+ struct btrfs_qgroup_list *glist;
+ struct ulist_node *unode;
+ struct ulist_iterator uiter;
++ u64 num_bytes = src->excl;
+ int ret = 0;
+
+ qgroup = find_qgroup_rb(fs_info, ref_root);
+@@ -1094,13 +1103,11 @@ static int __qgroup_excl_accounting(stru
+ WARN_ON(sign < 0 && qgroup->excl < num_bytes);
+ qgroup->excl += sign * num_bytes;
+ qgroup->excl_cmpr += sign * num_bytes;
+- if (sign > 0) {
+- trace_qgroup_update_reserve(fs_info, qgroup, -(s64)num_bytes);
+- if (qgroup->reserved < num_bytes)
+- report_reserved_underflow(fs_info, qgroup, num_bytes);
+- else
+- qgroup->reserved -= num_bytes;
+- }
++
++ if (sign > 0)
++ qgroup_rsv_add_by_qgroup(qgroup, src);
++ else
++ qgroup_rsv_release_by_qgroup(qgroup, src);
+
+ qgroup_dirty(fs_info, qgroup);
+
+@@ -1120,15 +1127,10 @@ static int __qgroup_excl_accounting(stru
+ qgroup->rfer_cmpr += sign * num_bytes;
+ WARN_ON(sign < 0 && qgroup->excl < num_bytes);
+ qgroup->excl += sign * num_bytes;
+- if (sign > 0) {
+- trace_qgroup_update_reserve(fs_info, qgroup,
+- -(s64)num_bytes);
+- if (qgroup->reserved < num_bytes)
+- report_reserved_underflow(fs_info, qgroup,
+- num_bytes);
+- else
+- qgroup->reserved -= num_bytes;
+- }
++ if (sign > 0)
++ qgroup_rsv_add_by_qgroup(qgroup, src);
++ else
++ qgroup_rsv_release_by_qgroup(qgroup, src);
+ qgroup->excl_cmpr += sign * num_bytes;
+ qgroup_dirty(fs_info, qgroup);
+
+@@ -1171,7 +1173,7 @@ static int quick_update_accounting(struc
+ if (qgroup->excl == qgroup->rfer) {
+ ret = 0;
+ err = __qgroup_excl_accounting(fs_info, tmp, dst,
+- qgroup->excl, sign);
++ qgroup, sign);
+ if (err < 0) {
+ ret = err;
+ goto out;
diff --git a/patches.suse/0011-btrfs-qgroup-Update-trace-events-to-use-new-separate.patch b/patches.suse/0011-btrfs-qgroup-Update-trace-events-to-use-new-separate.patch
new file mode 100644
index 0000000000..0ad10501ff
--- /dev/null
+++ b/patches.suse/0011-btrfs-qgroup-Update-trace-events-to-use-new-separate.patch
@@ -0,0 +1,162 @@
+From 64ee4e751a1c43b155afe2c1c07212893836f36d Mon Sep 17 00:00:00 2001
+From: Qu Wenruo <wqu@suse.com>
+Date: Tue, 12 Dec 2017 15:34:27 +0800
+Patch-mainline: v4.17-rc1
+Git-commit: 64ee4e751a1c43b155afe2c1c07212893836f36d
+References: bsc#1031392
+Subject: [PATCH 11/16] btrfs: qgroup: Update trace events to use new separate
+ rsv types
+
+Signed-off-by: Qu Wenruo <wqu@suse.com>
+Signed-off-by: David Sterba <dsterba@suse.com>
+---
+ fs/btrfs/qgroup.c | 36 +++++++++++++++++++++---------------
+ include/trace/events/btrfs.h | 17 ++++++++++++-----
+ 2 files changed, 33 insertions(+), 20 deletions(-)
+
+--- a/fs/btrfs/qgroup.c
++++ b/fs/btrfs/qgroup.c
+@@ -75,15 +75,19 @@ static const char *qgroup_rsv_type_str(e
+ }
+ #endif
+
+-static void qgroup_rsv_add(struct btrfs_qgroup *qgroup, u64 num_bytes,
++static void qgroup_rsv_add(struct btrfs_fs_info *fs_info,
++ struct btrfs_qgroup *qgroup, u64 num_bytes,
+ enum btrfs_qgroup_rsv_type type)
+ {
++ trace_qgroup_update_reserve(fs_info, qgroup, num_bytes, type);
+ qgroup->rsv.values[type] += num_bytes;
+ }
+
+-static void qgroup_rsv_release(struct btrfs_qgroup *qgroup, u64 num_bytes,
++static void qgroup_rsv_release(struct btrfs_fs_info *fs_info,
++ struct btrfs_qgroup *qgroup, u64 num_bytes,
+ enum btrfs_qgroup_rsv_type type)
+ {
++ trace_qgroup_update_reserve(fs_info, qgroup, -(s64)num_bytes, type);
+ if (qgroup->rsv.values[type] >= num_bytes) {
+ qgroup->rsv.values[type] -= num_bytes;
+ return;
+@@ -97,22 +101,24 @@ static void qgroup_rsv_release(struct bt
+ qgroup->rsv.values[type] = 0;
+ }
+
+-static void qgroup_rsv_add_by_qgroup(struct btrfs_qgroup *dest,
+- struct btrfs_qgroup *src)
++static void qgroup_rsv_add_by_qgroup(struct btrfs_fs_info *fs_info,
++ struct btrfs_qgroup *dest,
++ struct btrfs_qgroup *src)
+ {
+ int i;
+
+ for (i = 0; i < BTRFS_QGROUP_RSV_LAST; i++)
+- qgroup_rsv_add(dest, src->rsv.values[i], i);
++ qgroup_rsv_add(fs_info, dest, src->rsv.values[i], i);
+ }
+
+-static void qgroup_rsv_release_by_qgroup(struct btrfs_qgroup *dest,
++static void qgroup_rsv_release_by_qgroup(struct btrfs_fs_info *fs_info,
++ struct btrfs_qgroup *dest,
+ struct btrfs_qgroup *src)
+ {
+ int i;
+
+ for (i = 0; i < BTRFS_QGROUP_RSV_LAST; i++)
+- qgroup_rsv_release(dest, src->rsv.values[i], i);
++ qgroup_rsv_release(fs_info, dest, src->rsv.values[i], i);
+ }
+
+ static void btrfs_qgroup_update_old_refcnt(struct btrfs_qgroup *qg, u64 seq,
+@@ -1105,9 +1111,9 @@ static int __qgroup_excl_accounting(stru
+ qgroup->excl_cmpr += sign * num_bytes;
+
+ if (sign > 0)
+- qgroup_rsv_add_by_qgroup(qgroup, src);
++ qgroup_rsv_add_by_qgroup(fs_info, qgroup, src);
+ else
+- qgroup_rsv_release_by_qgroup(qgroup, src);
++ qgroup_rsv_release_by_qgroup(fs_info, qgroup, src);
+
+ qgroup_dirty(fs_info, qgroup);
+
+@@ -1128,9 +1134,9 @@ static int __qgroup_excl_accounting(stru
+ WARN_ON(sign < 0 && qgroup->excl < num_bytes);
+ qgroup->excl += sign * num_bytes;
+ if (sign > 0)
+- qgroup_rsv_add_by_qgroup(qgroup, src);
++ qgroup_rsv_add_by_qgroup(fs_info, qgroup, src);
+ else
+- qgroup_rsv_release_by_qgroup(qgroup, src);
++ qgroup_rsv_release_by_qgroup(fs_info, qgroup, src);
+ qgroup->excl_cmpr += sign * num_bytes;
+ qgroup_dirty(fs_info, qgroup);
+
+@@ -2477,8 +2483,8 @@ retry:
+
+ qg = u64_to_ptr(unode->aux);
+
+- trace_qgroup_update_reserve(fs_info, qg, num_bytes);
+- qgroup_rsv_add(qg, num_bytes, type);
++ trace_qgroup_update_reserve(fs_info, qg, num_bytes, type);
++ qgroup_rsv_add(fs_info, qg, num_bytes, type);
+ }
+
+ out:
+@@ -2524,8 +2530,8 @@ void btrfs_qgroup_free_refroot(struct bt
+
+ qg = u64_to_ptr(unode->aux);
+
+- trace_qgroup_update_reserve(fs_info, qg, -(s64)num_bytes);
+- qgroup_rsv_release(qg, num_bytes, type);
++ trace_qgroup_update_reserve(fs_info, qg, -(s64)num_bytes, type);
++ qgroup_rsv_release(fs_info, qg, num_bytes, type);
+
+ list_for_each_entry(glist, &qg->groups, next_group) {
+ ret = ulist_add(fs_info->qgroup_ulist,
+--- a/include/trace/events/btrfs.h
++++ b/include/trace/events/btrfs.h
+@@ -55,6 +55,11 @@ struct btrfs_qgroup;
+ (obj >= BTRFS_ROOT_TREE_OBJECTID && \
+ obj <= BTRFS_QUOTA_TREE_OBJECTID)) ? __show_root_type(obj) : "-"
+
++#define show_qgroup_rsv_type(type) \
++ __print_symbolic(type, \
++ { BTRFS_QGROUP_RSV_DATA, "DATA" }, \
++ { BTRFS_QGROUP_RSV_META, "META" })
++
+ #define BTRFS_GROUP_FLAGS \
+ { BTRFS_BLOCK_GROUP_DATA, "DATA"}, \
+ { BTRFS_BLOCK_GROUP_SYSTEM, "SYSTEM"}, \
+@@ -1547,24 +1552,26 @@ DEFINE_EVENT(btrfs__prelim_ref, btrfs_pr
+ TRACE_EVENT(qgroup_update_reserve,
+
+ TP_PROTO(struct btrfs_fs_info *fs_info, struct btrfs_qgroup *qgroup,
+- s64 diff),
++ s64 diff, int type),
+
+- TP_ARGS(fs_info, qgroup, diff),
++ TP_ARGS(fs_info, qgroup, diff, type),
+
+ TP_STRUCT__entry_btrfs(
+ __field( u64, qgid )
+ __field( u64, cur_reserved )
+ __field( s64, diff )
++ __field( int, type )
+ ),
+
+ TP_fast_assign_btrfs(fs_info,
+ __entry->qgid = qgroup->qgroupid;
+- __entry->cur_reserved = qgroup->reserved;
++ __entry->cur_reserved = qgroup->rsv.values[type];
+ __entry->diff = diff;
+ ),
+
+- TP_printk_btrfs("qgid=%llu cur_reserved=%llu diff=%lld",
+- __entry->qgid, __entry->cur_reserved, __entry->diff)
++ TP_printk_btrfs("qgid=%llu type=%s cur_reserved=%llu diff=%lld",
++ __entry->qgid, show_qgroup_rsv_type(__entry->type),
++ __entry->cur_reserved, __entry->diff)
+ );
+
+ TRACE_EVENT(qgroup_meta_reserve,
diff --git a/patches.suse/0012-btrfs-qgroup-Cleanup-the-remaining-old-reservation-c.patch b/patches.suse/0012-btrfs-qgroup-Cleanup-the-remaining-old-reservation-c.patch
new file mode 100644
index 0000000000..e59702e0be
--- /dev/null
+++ b/patches.suse/0012-btrfs-qgroup-Cleanup-the-remaining-old-reservation-c.patch
@@ -0,0 +1,57 @@
+From 5c40507ffb1bbbc8eeeaa6d8da181f431cb83d97 Mon Sep 17 00:00:00 2001
+From: Qu Wenruo <wqu@suse.com>
+Date: Tue, 12 Dec 2017 15:34:28 +0800
+Patch-mainline: v4.17-rc1
+Git-commit: 5c40507ffb1bbbc8eeeaa6d8da181f431cb83d97
+References: bsc#1031392
+Subject: [PATCH 12/16] btrfs: qgroup: Cleanup the remaining old reservation
+ counters
+
+So qgroup is switched to new separate types reservation system.
+
+Signed-off-by: Qu Wenruo <wqu@suse.com>
+Signed-off-by: David Sterba <dsterba@suse.com>
+---
+ fs/btrfs/qgroup.c | 13 -------------
+ fs/btrfs/qgroup.h | 1 -
+ 2 files changed, 14 deletions(-)
+
+diff --git a/fs/btrfs/qgroup.c b/fs/btrfs/qgroup.c
+index 8ec103deb361..c0deebfecd93 100644
+--- a/fs/btrfs/qgroup.c
++++ b/fs/btrfs/qgroup.c
+@@ -1070,19 +1070,6 @@ static void qgroup_dirty(struct btrfs_fs_info *fs_info,
+ list_add(&qgroup->dirty, &fs_info->dirty_qgroups);
+ }
+
+-static void report_reserved_underflow(struct btrfs_fs_info *fs_info,
+- struct btrfs_qgroup *qgroup,
+- u64 num_bytes)
+-{
+-#ifdef CONFIG_BTRFS_DEBUG
+- WARN_ON(qgroup->reserved < num_bytes);
+- btrfs_debug(fs_info,
+- "qgroup %llu reserved space underflow, have: %llu, to free: %llu",
+- qgroup->qgroupid, qgroup->reserved, num_bytes);
+-#endif
+- qgroup->reserved = 0;
+-}
+-
+ /*
+ * The easy accounting, we're updating qgroup relationship whose child qgroup
+ * only has exclusive extents.
+diff --git a/fs/btrfs/qgroup.h b/fs/btrfs/qgroup.h
+index b5ee229b3ef1..279e71a21695 100644
+--- a/fs/btrfs/qgroup.h
++++ b/fs/btrfs/qgroup.h
+@@ -107,7 +107,6 @@ struct btrfs_qgroup {
+ /*
+ * reservation tracking
+ */
+- u64 reserved;
+ struct btrfs_qgroup_rsv rsv;
+
+ /*
+--
+2.19.0
+
diff --git a/patches.suse/0013-btrfs-qgroup-Split-meta-rsv-type-into-meta_prealloc-.patch b/patches.suse/0013-btrfs-qgroup-Split-meta-rsv-type-into-meta_prealloc-.patch
new file mode 100644
index 0000000000..9fe4f9dc9a
--- /dev/null
+++ b/patches.suse/0013-btrfs-qgroup-Split-meta-rsv-type-into-meta_prealloc-.patch
@@ -0,0 +1,287 @@
+From 733e03a0b26a463d75aa86083c9fab856571e7fc Mon Sep 17 00:00:00 2001
+From: Qu Wenruo <wqu@suse.com>
+Date: Tue, 12 Dec 2017 15:34:29 +0800
+Patch-mainline: v4.17-rc1
+Git-commit: 733e03a0b26a463d75aa86083c9fab856571e7fc
+References: bsc#1031392
+Subject: [PATCH 13/16] btrfs: qgroup: Split meta rsv type into meta_prealloc
+ and meta_pertrans
+
+Btrfs uses 2 different methods to reseve metadata qgroup space.
+
+1) Reserve at btrfs_start_transaction() time
+ This is quite straightforward, caller will use the trans handler
+ allocated to modify b-trees.
+
+ In this case, reserved metadata should be kept until qgroup numbers
+ are updated.
+
+2) Reserve by using block_rsv first, and later btrfs_join_transaction()
+ This is more complicated, caller will reserve space using block_rsv
+ first, and then later call btrfs_join_transaction() to get a trans
+ handle.
+
+ In this case, before we modify trees, the reserved space can be
+ modified on demand, and after btrfs_join_transaction(), such reserved
+ space should also be kept until qgroup numbers are updated.
+
+Since these two types behave differently, split the original "META"
+reservation type into 2 sub-types:
+
+ META_PERTRANS:
+ For above case 1)
+
+ META_PREALLOC:
+ For reservations that happened before btrfs_join_transaction() of
+ case 2)
+
+NOTE: This patch will only convert existing qgroup meta reservation
+callers according to its situation, not ensuring all callers are at
+correct timing.
+Such fix will be added in later patches.
+
+Signed-off-by: Qu Wenruo <wqu@suse.com>
+[ update comments ]
+Signed-off-by: David Sterba <dsterba@suse.com>
+---
+ fs/btrfs/extent-tree.c | 9 +++--
+ fs/btrfs/qgroup.c | 21 +++++++------
+ fs/btrfs/qgroup.h | 69 +++++++++++++++++++++++++++++++++++++++----
+ fs/btrfs/transaction.c | 6 +--
+ include/trace/events/btrfs.h | 5 +--
+ 5 files changed, 87 insertions(+), 23 deletions(-)
+
+--- a/fs/btrfs/extent-tree.c
++++ b/fs/btrfs/extent-tree.c
+@@ -5863,7 +5863,7 @@ int btrfs_subvolume_reserve_metadata(str
+ if (test_bit(BTRFS_FS_QUOTA_ENABLED, &root->fs_info->flags)) {
+ /* One for parent inode, two for dir entries */
+ num_bytes = 3 * root->nodesize;
+- ret = btrfs_qgroup_reserve_meta(root, num_bytes, true);
++ ret = btrfs_qgroup_reserve_meta_prealloc(root, num_bytes, true);
+ if (ret)
+ return ret;
+ } else {
+@@ -5882,7 +5882,7 @@ int btrfs_subvolume_reserve_metadata(str
+ ret = btrfs_block_rsv_migrate(global_rsv, rsv, num_bytes, 1);
+
+ if (ret && *qgroup_reserved)
+- btrfs_qgroup_free_meta(root, *qgroup_reserved);
++ btrfs_qgroup_free_meta_prealloc(root, *qgroup_reserved);
+
+ return ret;
+ }
+@@ -6039,7 +6039,7 @@ int btrfs_delalloc_reserve_metadata(stru
+ spin_unlock(&BTRFS_I(inode)->lock);
+
+ if (test_bit(BTRFS_FS_QUOTA_ENABLED, &root->fs_info->flags)) {
+- ret = btrfs_qgroup_reserve_meta(root,
++ ret = btrfs_qgroup_reserve_meta_prealloc(root,
+ nr_extents * root->nodesize, true);
+ if (ret)
+ goto out_fail;
+@@ -6047,7 +6047,8 @@ int btrfs_delalloc_reserve_metadata(stru
+
+ ret = btrfs_block_rsv_add(root, block_rsv, to_reserve, flush);
+ if (unlikely(ret)) {
+- btrfs_qgroup_free_meta(root, nr_extents * root->nodesize);
++ btrfs_qgroup_free_meta_prealloc(root,
++ nr_extents * root->nodesize);
+ goto out_fail;
+ }
+
+--- a/fs/btrfs/qgroup.c
++++ b/fs/btrfs/qgroup.c
+@@ -69,8 +69,10 @@ static const char *qgroup_rsv_type_str(e
+ {
+ if (type == BTRFS_QGROUP_RSV_DATA)
+ return "data";
+- if (type == BTRFS_QGROUP_RSV_META)
+- return "meta";
++ if (type == BTRFS_QGROUP_RSV_META_PERTRANS)
++ return "meta_pertrans";
++ if (type == BTRFS_QGROUP_RSV_META_PREALLOC)
++ return "meta_prealloc";
+ return NULL;
+ }
+ #endif
+@@ -3081,8 +3083,8 @@ int btrfs_qgroup_release_data(struct ino
+ return __btrfs_qgroup_release_data(inode, NULL, start, len, 0);
+ }
+
+-int btrfs_qgroup_reserve_meta(struct btrfs_root *root, int num_bytes,
+- bool enforce)
++int __btrfs_qgroup_reserve_meta(struct btrfs_root *root, int num_bytes,
++ enum btrfs_qgroup_rsv_type type, bool enforce)
+ {
+ int ret;
+
+@@ -3092,14 +3094,14 @@ int btrfs_qgroup_reserve_meta(struct btr
+
+ BUG_ON(num_bytes != round_down(num_bytes, root->nodesize));
+ trace_qgroup_meta_reserve(root, (s64)num_bytes);
+- ret = qgroup_reserve(root, num_bytes, enforce, BTRFS_QGROUP_RSV_META);
++ ret = qgroup_reserve(root, num_bytes, enforce, type);
+ if (ret < 0)
+ return ret;
+ atomic64_add(num_bytes, &root->qgroup_meta_rsv);
+ return ret;
+ }
+
+-void btrfs_qgroup_free_meta_all(struct btrfs_root *root)
++void btrfs_qgroup_free_meta_all_pertrans(struct btrfs_root *root)
+ {
+ u64 reserved;
+
+@@ -3112,10 +3114,11 @@ void btrfs_qgroup_free_meta_all(struct b
+ return;
+ trace_qgroup_meta_reserve(root, -(s64)reserved);
+ btrfs_qgroup_free_refroot(root->fs_info, root->objectid, reserved,
+- BTRFS_QGROUP_RSV_META);
++ BTRFS_QGROUP_RSV_META_PERTRANS);
+ }
+
+-void btrfs_qgroup_free_meta(struct btrfs_root *root, int num_bytes)
++void __btrfs_qgroup_free_meta(struct btrfs_root *root, int num_bytes,
++ enum btrfs_qgroup_rsv_type type)
+ {
+ if (!test_bit(BTRFS_FS_QUOTA_ENABLED, &root->fs_info->flags) ||
+ !is_fstree(root->objectid))
+@@ -3126,7 +3129,7 @@ void btrfs_qgroup_free_meta(struct btrfs
+ atomic64_sub(num_bytes, &root->qgroup_meta_rsv);
+ trace_qgroup_meta_reserve(root, -(s64)num_bytes);
+ btrfs_qgroup_free_refroot(root->fs_info, root->objectid, num_bytes,
+- BTRFS_QGROUP_RSV_META);
++ type);
+ }
+
+ /*
+--- a/fs/btrfs/qgroup.h
++++ b/fs/btrfs/qgroup.h
+@@ -33,9 +33,31 @@ struct btrfs_qgroup_extent_record {
+ struct ulist *old_roots;
+ };
+
++/*
++ * Qgroup reservation types:
++ *
++ * DATA:
++ * space reserved for data
++ *
++ * META_PERTRANS:
++ * Space reserved for metadata (per-transaction)
++ * Due to the fact that qgroup data is only updated at transaction commit
++ * time, reserved space for metadata must be kept until transaction
++ * commits.
++ * Any metadata reserved that are used in btrfs_start_transaction() should
++ * be of this type.
++ *
++ * META_PREALLOC:
++ * There are cases where metadata space is reserved before starting
++ * transaction, and then btrfs_join_transaction() to get a trans handle.
++ * Any metadata reserved for such usage should be of this type.
++ * And after join_transaction() part (or all) of such reservation should
++ * be converted into META_PERTRANS.
++ */
+ enum btrfs_qgroup_rsv_type {
+ BTRFS_QGROUP_RSV_DATA = 0,
+- BTRFS_QGROUP_RSV_META,
++ BTRFS_QGROUP_RSV_META_PERTRANS,
++ BTRFS_QGROUP_RSV_META_PREALLOC,
+ BTRFS_QGROUP_RSV_LAST,
+ };
+
+@@ -220,9 +242,46 @@ int btrfs_qgroup_release_data(struct ino
+ int btrfs_qgroup_free_data(struct inode *inode,
+ struct extent_changeset *reserved, u64 start, u64 len);
+
+-int btrfs_qgroup_reserve_meta(struct btrfs_root *root, int num_bytes,
+- bool enforce);
+-void btrfs_qgroup_free_meta_all(struct btrfs_root *root);
+-void btrfs_qgroup_free_meta(struct btrfs_root *root, int num_bytes);
++int __btrfs_qgroup_reserve_meta(struct btrfs_root *root, int num_bytes,
++ enum btrfs_qgroup_rsv_type type, bool enforce);
++/* Reserve metadata space for pertrans and prealloc type */
++static inline int btrfs_qgroup_reserve_meta_pertrans(struct btrfs_root *root,
++ int num_bytes, bool enforce)
++{
++ return __btrfs_qgroup_reserve_meta(root, num_bytes,
++ BTRFS_QGROUP_RSV_META_PERTRANS, enforce);
++}
++static inline int btrfs_qgroup_reserve_meta_prealloc(struct btrfs_root *root,
++ int num_bytes, bool enforce)
++{
++ return __btrfs_qgroup_reserve_meta(root, num_bytes,
++ BTRFS_QGROUP_RSV_META_PREALLOC, enforce);
++}
++
++void __btrfs_qgroup_free_meta(struct btrfs_root *root, int num_bytes,
++ enum btrfs_qgroup_rsv_type type);
++
++/* Free per-transaction meta reservation for error handling */
++static inline void btrfs_qgroup_free_meta_pertrans(struct btrfs_root *root,
++ int num_bytes)
++{
++ __btrfs_qgroup_free_meta(root, num_bytes,
++ BTRFS_QGROUP_RSV_META_PERTRANS);
++}
++
++/* Pre-allocated meta reservation can be freed at need */
++static inline void btrfs_qgroup_free_meta_prealloc(struct btrfs_root *root,
++ int num_bytes)
++{
++ __btrfs_qgroup_free_meta(root, num_bytes,
++ BTRFS_QGROUP_RSV_META_PREALLOC);
++}
++
++/*
++ * Per-transaction meta reservation should be all freed at transaction commit
++ * time
++ */
++void btrfs_qgroup_free_meta_all_pertrans(struct btrfs_root *root);
++
+ void btrfs_qgroup_check_reserved_leak(struct inode *inode);
+ #endif /* __BTRFS_QGROUP__ */
+--- a/fs/btrfs/transaction.c
++++ b/fs/btrfs/transaction.c
+@@ -499,7 +499,7 @@ start_transaction(struct btrfs_root *roo
+ */
+ if (num_items > 0 && root != root->fs_info->chunk_root) {
+ qgroup_reserved = num_items * root->nodesize;
+- ret = btrfs_qgroup_reserve_meta(root, qgroup_reserved,
++ ret = btrfs_qgroup_reserve_meta_pertrans(root, qgroup_reserved,
+ enforce_qgroups);
+ if (ret)
+ return ERR_PTR(ret);
+@@ -599,7 +599,7 @@ alloc_fail:
+ btrfs_block_rsv_release(root, &root->fs_info->trans_block_rsv,
+ num_bytes);
+ reserve_fail:
+- btrfs_qgroup_free_meta(root, qgroup_reserved);
++ btrfs_qgroup_free_meta_pertrans(root, qgroup_reserved);
+ return ERR_PTR(ret);
+ }
+
+@@ -1270,7 +1270,7 @@ static noinline int commit_fs_roots(stru
+ spin_lock(&fs_info->fs_roots_radix_lock);
+ if (err)
+ break;
+- btrfs_qgroup_free_meta_all(root);
++ btrfs_qgroup_free_meta_all_pertrans(root);
+ }
+ }
+ spin_unlock(&fs_info->fs_roots_radix_lock);
+--- a/include/trace/events/btrfs.h
++++ b/include/trace/events/btrfs.h
+@@ -57,8 +57,9 @@ struct btrfs_qgroup;
+
+ #define show_qgroup_rsv_type(type) \
+ __print_symbolic(type, \
+- { BTRFS_QGROUP_RSV_DATA, "DATA" }, \
+- { BTRFS_QGROUP_RSV_META, "META" })
++ { BTRFS_QGROUP_RSV_DATA, "DATA" }, \
++ { BTRFS_QGROUP_RSV_META_PERTRANS, "META_PERTRANS" }, \
++ { BTRFS_QGROUP_RSV_META_PREALLOC, "META_PREALLOC" })
+
+ #define BTRFS_GROUP_FLAGS \
+ { BTRFS_BLOCK_GROUP_DATA, "DATA"}, \
diff --git a/patches.suse/0014-btrfs-qgroup-Don-t-use-root-qgroup_meta_rsv-for-qgro.patch b/patches.suse/0014-btrfs-qgroup-Don-t-use-root-qgroup_meta_rsv-for-qgro.patch
new file mode 100644
index 0000000000..43d8a88d9e
--- /dev/null
+++ b/patches.suse/0014-btrfs-qgroup-Don-t-use-root-qgroup_meta_rsv-for-qgro.patch
@@ -0,0 +1,124 @@
+From e1211d0e896b71d395fe411d0e0a76f4bc336617 Mon Sep 17 00:00:00 2001
+From: Qu Wenruo <wqu@suse.com>
+Date: Tue, 12 Dec 2017 15:34:30 +0800
+Patch-mainline: v4.17-rc1
+Git-commit: e1211d0e896b71d395fe411d0e0a76f4bc336617
+References: bsc#1031392
+Subject: [PATCH 14/16] btrfs: qgroup: Don't use root->qgroup_meta_rsv for
+ qgroup
+
+Since qgroup has seperate metadata reservation types now, we can
+completely get rid of the old root->qgroup_meta_rsv, which mostly acts
+as current META_PERTRANS reservation type.
+
+Signed-off-by: Qu Wenruo <wqu@suse.com>
+Signed-off-by: David Sterba <dsterba@suse.com>
+---
+ fs/btrfs/ctree.h | 3 ---
+ fs/btrfs/disk-io.c | 1 -
+ fs/btrfs/qgroup.c | 34 +++++++++++++++++++++++++---------
+ 3 files changed, 25 insertions(+), 13 deletions(-)
+
+--- a/fs/btrfs/ctree.h
++++ b/fs/btrfs/ctree.h
+@@ -1224,9 +1224,6 @@ struct btrfs_root {
+ int send_in_progress;
+ struct btrfs_subvolume_writers *subv_writers;
+ atomic_t will_be_snapshoted;
+-
+- /* For qgroup metadata space reserve */
+- atomic64_t qgroup_meta_rsv;
+ };
+
+ static inline u32 __BTRFS_LEAF_DATA_SIZE(u32 blocksize)
+--- a/fs/btrfs/disk-io.c
++++ b/fs/btrfs/disk-io.c
+@@ -1287,7 +1287,6 @@ static void __setup_root(u32 nodesize, u
+ atomic_set(&root->orphan_inodes, 0);
+ atomic_set(&root->refs, 1);
+ atomic_set(&root->will_be_snapshoted, 0);
+- atomic64_set(&root->qgroup_meta_rsv, 0);
+ root->log_transid = 0;
+ root->log_transid_committed = -1;
+ root->last_log_commit = 0;
+--- a/fs/btrfs/qgroup.c
++++ b/fs/btrfs/qgroup.c
+@@ -2481,6 +2481,15 @@ out:
+ return ret;
+ }
+
++/*
++ * Free @num_bytes of reserved space with @type for qgroup. (Normally level 0
++ * qgroup).
++ *
++ * Will handle all higher level qgroup too.
++ *
++ * NOTE: If @num_bytes is (u64)-1, this means to free all bytes of this qgroup.
++ * This special case is only used for META_PERTRANS type.
++ */
+ void btrfs_qgroup_free_refroot(struct btrfs_fs_info *fs_info,
+ u64 ref_root, u64 num_bytes,
+ enum btrfs_qgroup_rsv_type type)
+@@ -2497,6 +2506,10 @@ void btrfs_qgroup_free_refroot(struct bt
+ if (num_bytes == 0)
+ return;
+
++ if (num_bytes == (u64)-1 && type != BTRFS_QGROUP_RSV_META_PERTRANS) {
++ WARN(1, "%s: Invalid type to free", __func__);
++ return;
++ }
+ spin_lock(&fs_info->qgroup_lock);
+
+ quota_root = fs_info->quota_root;
+@@ -2507,6 +2520,13 @@ void btrfs_qgroup_free_refroot(struct bt
+ if (!qgroup)
+ goto out;
+
++ /*
++ * We're freeing all pertrans rsv, get current value from level 0
++ * qgroup as real num_bytes to free.
++ */
++ if (num_bytes == (u64)-1)
++ num_bytes = qgroup->rsv.values[type];
++
+ ulist_reinit(fs_info->qgroup_ulist);
+ ret = ulist_add(fs_info->qgroup_ulist, qgroup->qgroupid,
+ (uintptr_t)qgroup, GFP_ATOMIC);
+@@ -3097,23 +3117,21 @@ int __btrfs_qgroup_reserve_meta(struct b
+ ret = qgroup_reserve(root, num_bytes, enforce, type);
+ if (ret < 0)
+ return ret;
+- atomic64_add(num_bytes, &root->qgroup_meta_rsv);
+ return ret;
+ }
+
+ void btrfs_qgroup_free_meta_all_pertrans(struct btrfs_root *root)
+ {
+- u64 reserved;
++ struct btrfs_fs_info *fs_info = root->fs_info;
+
+ if (!test_bit(BTRFS_FS_QUOTA_ENABLED, &root->fs_info->flags) ||
+ !is_fstree(root->objectid))
+ return;
+
+- reserved = atomic64_xchg(&root->qgroup_meta_rsv, 0);
+- if (reserved == 0)
+- return;
+- trace_qgroup_meta_reserve(root, -(s64)reserved);
+- btrfs_qgroup_free_refroot(root->fs_info, root->objectid, reserved,
++ /* TODO: Update trace point to handle such free */
++ trace_qgroup_meta_reserve(root, 0);
++ /* Special value -1 means to free all reserved space */
++ btrfs_qgroup_free_refroot(fs_info, root->objectid, (u64)-1,
+ BTRFS_QGROUP_RSV_META_PERTRANS);
+ }
+
+@@ -3125,8 +3143,6 @@ void __btrfs_qgroup_free_meta(struct btr
+ return;
+
+ BUG_ON(num_bytes != round_down(num_bytes, root->nodesize));
+- WARN_ON(atomic64_read(&root->qgroup_meta_rsv) < num_bytes);
+- atomic64_sub(num_bytes, &root->qgroup_meta_rsv);
+ trace_qgroup_meta_reserve(root, -(s64)num_bytes);
+ btrfs_qgroup_free_refroot(root->fs_info, root->objectid, num_bytes,
+ type);
diff --git a/patches.suse/0015-btrfs-qgroup-Introduce-function-to-convert-META_PREA.patch b/patches.suse/0015-btrfs-qgroup-Introduce-function-to-convert-META_PREA.patch
new file mode 100644
index 0000000000..10f1c998a5
--- /dev/null
+++ b/patches.suse/0015-btrfs-qgroup-Introduce-function-to-convert-META_PREA.patch
@@ -0,0 +1,110 @@
+From 64cfaef6362fc756972f477372997fbe117d79cb Mon Sep 17 00:00:00 2001
+From: Qu Wenruo <wqu@suse.com>
+Date: Tue, 12 Dec 2017 15:34:31 +0800
+Patch-mainline: v4.17-rc1
+Git-commit: 64cfaef6362fc756972f477372997fbe117d79cb
+References: bsc#1031392
+Subject: [PATCH 15/16] btrfs: qgroup: Introduce function to convert
+ META_PREALLOC into META_PERTRANS
+
+For meta_prealloc reservation users, after btrfs_join_transaction()
+caller will modify tree so part (or even all) meta_prealloc reservation
+should be converted to meta_pertrans until transaction commit time.
+
+This patch introduces a new function,
+btrfs_qgroup_convert_reserved_meta() to do this for META_PREALLOC
+reservation user.
+
+Signed-off-by: Qu Wenruo <wqu@suse.com>
+Signed-off-by: David Sterba <dsterba@suse.com>
+---
+ fs/btrfs/qgroup.c | 61 ++++++++++++++++++++++++++++++++++++++++++++++++++++++
+ fs/btrfs/qgroup.h | 8 +++++++
+ 2 files changed, 69 insertions(+)
+
+--- a/fs/btrfs/qgroup.c
++++ b/fs/btrfs/qgroup.c
+@@ -3148,6 +3148,67 @@ void __btrfs_qgroup_free_meta(struct btr
+ type);
+ }
+
++static inline struct btrfs_qgroup* unode_aux_to_qgroup(struct ulist_node *n)
++{
++ return (struct btrfs_qgroup *)(uintptr_t)n->aux;
++}
++
++static void qgroup_convert_meta(struct btrfs_fs_info *fs_info, u64 ref_root,
++ int num_bytes)
++{
++ struct btrfs_root *quota_root = fs_info->quota_root;
++ struct btrfs_qgroup *qgroup;
++ struct ulist_node *unode;
++ struct ulist_iterator uiter;
++ int ret = 0;
++
++ if (num_bytes == 0)
++ return;
++ if (!quota_root)
++ return;
++
++ spin_lock(&fs_info->qgroup_lock);
++ qgroup = find_qgroup_rb(fs_info, ref_root);
++ if (!qgroup)
++ goto out;
++ ulist_reinit(fs_info->qgroup_ulist);
++ ret = ulist_add(fs_info->qgroup_ulist, qgroup->qgroupid,
++ (uintptr_t)qgroup, GFP_ATOMIC);
++ if (ret < 0)
++ goto out;
++ ULIST_ITER_INIT(&uiter);
++ while ((unode = ulist_next(fs_info->qgroup_ulist, &uiter))) {
++ struct btrfs_qgroup *qg;
++ struct btrfs_qgroup_list *glist;
++
++ qg = unode_aux_to_qgroup(unode);
++
++ qgroup_rsv_release(fs_info, qg, num_bytes,
++ BTRFS_QGROUP_RSV_META_PREALLOC);
++ qgroup_rsv_add(fs_info, qg, num_bytes,
++ BTRFS_QGROUP_RSV_META_PERTRANS);
++ list_for_each_entry(glist, &qg->groups, next_group) {
++ ret = ulist_add(fs_info->qgroup_ulist,
++ glist->group->qgroupid,
++ (uintptr_t)glist->group, GFP_ATOMIC);
++ if (ret < 0)
++ goto out;
++ }
++ }
++out:
++ spin_unlock(&fs_info->qgroup_lock);
++}
++
++void btrfs_qgroup_convert_reserved_meta(struct btrfs_root *root, int num_bytes)
++{
++ struct btrfs_fs_info *fs_info = root->fs_info;
++
++ if (!test_bit(BTRFS_FS_QUOTA_ENABLED, &fs_info->flags) ||
++ !is_fstree(root->objectid))
++ return;
++ qgroup_convert_meta(fs_info, root->objectid, num_bytes);
++}
++
+ /*
+ * Check qgroup reserved space leaking, normally at destory inode
+ * time
+--- a/fs/btrfs/qgroup.h
++++ b/fs/btrfs/qgroup.h
+@@ -283,5 +283,13 @@ static inline void btrfs_qgroup_free_met
+ */
+ void btrfs_qgroup_free_meta_all_pertrans(struct btrfs_root *root);
+
++/*
++ * Convert @num_bytes of META_PREALLOCATED reservation to META_PERTRANS.
++ *
++ * This is called when preallocated meta reservation needs to be used.
++ * Normally after btrfs_join_transaction() call.
++ */
++void btrfs_qgroup_convert_reserved_meta(struct btrfs_root *root, int num_bytes);
++
+ void btrfs_qgroup_check_reserved_leak(struct inode *inode);
+ #endif /* __BTRFS_QGROUP__ */
diff --git a/patches.suse/0016-btrfs-cleanup-extent-locking-sequence.patch b/patches.suse/0016-btrfs-cleanup-extent-locking-sequence.patch
new file mode 100644
index 0000000000..a697a50b33
--- /dev/null
+++ b/patches.suse/0016-btrfs-cleanup-extent-locking-sequence.patch
@@ -0,0 +1,81 @@
+From 79f015f216539dfdf0d3ef0b3bbb9dc7754364cd Mon Sep 17 00:00:00 2001
+From: Goldwyn Rodrigues <rgoldwyn@suse.com>
+Date: Mon, 16 Oct 2017 05:43:21 -0500
+Patch-mainline: v4.15
+Git-commit: 79f015f216539dfdf0d3ef0b3bbb9dc7754364cd
+References: dependency for bsc#1031392
+Subject: [PATCH] btrfs: cleanup extent locking sequence
+
+Code cleanup for better understanding:
+Variable needs_unlock to be called extent_locked to show state as
+opposed to action. Changed the type to int, to reduce code in the
+critical path.
+
+Signed-off-by: Goldwyn Rodrigues <rgoldwyn@suse.com>
+Reviewed-by: David Sterba <dsterba@suse.com>
+Signed-off-by: David Sterba <dsterba@suse.com>
+Signed-off-by: Qu Wenruo <wqu@suse.com>
+---
+ fs/btrfs/file.c | 22 ++++++++++------------
+ 1 file changed, 10 insertions(+), 12 deletions(-)
+
+--- a/fs/btrfs/file.c
++++ b/fs/btrfs/file.c
+@@ -1521,7 +1521,6 @@ static noinline ssize_t __btrfs_buffered
+ int ret = 0;
+ bool only_release_metadata = false;
+ bool force_page_uptodate = false;
+- bool need_unlock;
+
+ nrptrs = min(DIV_ROUND_UP(iov_iter_count(i), PAGE_CACHE_SIZE),
+ PAGE_CACHE_SIZE / (sizeof(struct page *)));
+@@ -1544,6 +1543,7 @@ static noinline ssize_t __btrfs_buffered
+ size_t copied;
+ size_t dirty_sectors;
+ size_t num_sectors;
++ int extents_locked;
+
+ WARN_ON(num_pages > nrptrs);
+
+@@ -1598,7 +1598,6 @@ static noinline ssize_t __btrfs_buffered
+ }
+
+ release_bytes = reserve_bytes;
+- need_unlock = false;
+ again:
+ /*
+ * This is going to setup the pages array with the number of
+@@ -1611,16 +1610,15 @@ again:
+ if (ret)
+ break;
+
+- ret = lock_and_cleanup_extent_if_need(inode, pages, num_pages,
+- pos, write_bytes, &lockstart,
+- &lockend, &cached_state);
+- if (ret < 0) {
+- if (ret == -EAGAIN)
+- goto again;
++ extents_locked = lock_and_cleanup_extent_if_need(
++ inode, pages,
++ num_pages, pos, write_bytes, &lockstart,
++ &lockend, &cached_state);
++ if (extents_locked < 0) {
++ if (extents_locked == -EAGAIN)
++ goto again;
++ ret = extents_locked;
+ break;
+- } else if (ret > 0) {
+- need_unlock = true;
+- ret = 0;
+ }
+
+ copied = btrfs_copy_from_user(pos, num_pages,
+@@ -1690,7 +1688,7 @@ again:
+ ret = btrfs_dirty_pages(root, inode, pages,
+ dirty_pages, pos, copied,
+ NULL);
+- if (need_unlock)
++ if (extents_locked)
+ unlock_extent_cached(&BTRFS_I(inode)->io_tree,
+ lockstart, lockend, &cached_state,
+ GFP_NOFS);
diff --git a/patches.suse/0017-Btrfs-rework-outstanding_extents.patch b/patches.suse/0017-Btrfs-rework-outstanding_extents.patch
new file mode 100644
index 0000000000..955d3188c2
--- /dev/null
+++ b/patches.suse/0017-Btrfs-rework-outstanding_extents.patch
@@ -0,0 +1,905 @@
+From 8b62f87bad9cf06e536799bf8cb942ab95f6bfa4 Mon Sep 17 00:00:00 2001
+From: Josef Bacik <josef@toxicpanda.com>
+Date: Thu, 19 Oct 2017 14:15:55 -0400
+Patch-mainline: v4.15
+Git-commit: 8b62f87bad9cf06e536799bf8cb942ab95f6bfa4
+References: dependency for bsc#1031392
+Subject: [PATCH 17/24] Btrfs: rework outstanding_extents
+
+Right now we do a lot of weird hoops around outstanding_extents in order
+to keep the extent count consistent. This is because we logically
+transfer the outstanding_extent count from the initial reservation
+through the set_delalloc_bits. This makes it pretty difficult to get a
+handle on how and when we need to mess with outstanding_extents.
+
+Fix this by revamping the rules of how we deal with outstanding_extents.
+Now instead everybody that is holding on to a delalloc extent is
+required to increase the outstanding extents count for itself. This
+means we'll have something like this
+
+btrfs_delalloc_reserve_metadata - outstanding_extents = 1
+ btrfs_set_extent_delalloc - outstanding_extents = 2
+btrfs_release_delalloc_extents - outstanding_extents = 1
+
+for an initial file write. Now take the append write where we extend an
+existing delalloc range but still under the maximum extent size
+
+btrfs_delalloc_reserve_metadata - outstanding_extents = 2
+ btrfs_set_extent_delalloc
+ btrfs_set_bit_hook - outstanding_extents = 3
+ btrfs_merge_extent_hook - outstanding_extents = 2
+btrfs_delalloc_release_extents - outstanding_extnets = 1
+
+In order to make the ordered extent transition we of course must now
+make ordered extents carry their own outstanding_extent reservation, so
+for cow_file_range we end up with
+
+btrfs_add_ordered_extent - outstanding_extents = 2
+clear_extent_bit - outstanding_extents = 1
+btrfs_remove_ordered_extent - outstanding_extents = 0
+
+This makes all manipulations of outstanding_extents much more explicit.
+Every successful call to btrfs_delalloc_reserve_metadata _must_ now be
+combined with btrfs_release_delalloc_extents, even in the error case, as
+that is the only function that actually modifies the
+outstanding_extents counter.
+
+The drawback to this is now we are much more likely to have transient
+cases where outstanding_extents is much larger than it actually should
+be. This could happen before as we manipulated the delalloc bits, but
+now it happens basically at every write. This may put more pressure on
+the ENOSPC flushing code, but I think making this code simpler is worth
+the cost. I have another change coming to mitigate this side-effect
+somewhat.
+
+I also added trace points for the counter manipulation. These were used
+by a bpf script I wrote to help track down leak issues.
+
+Signed-off-by: Josef Bacik <jbacik@fb.com>
+Signed-off-by: David Sterba <dsterba@suse.com>
+Signed-off-by: Qu Wenruo <wqu@suse.com>
+---
+ fs/btrfs/btrfs_inode.h | 17 ++++
+ fs/btrfs/ctree.h | 11 +++
+ fs/btrfs/extent-tree.c | 147 +++++++++++++++++++++++++++----------------
+ fs/btrfs/file.c | 22 ++----
+ fs/btrfs/inode-map.c | 3
+ fs/btrfs/inode.c | 112 ++++++++++----------------------
+ fs/btrfs/ioctl.c | 2
+ fs/btrfs/ordered-data.c | 21 +++++-
+ fs/btrfs/relocation.c | 3
+ fs/btrfs/tests/inode-tests.c | 17 +---
+ 10 files changed, 197 insertions(+), 158 deletions(-)
+
+--- a/fs/btrfs/btrfs_inode.h
++++ b/fs/btrfs/btrfs_inode.h
+@@ -255,6 +255,23 @@ static inline bool btrfs_is_free_space_i
+ return false;
+ }
+
++static inline void btrfs_mod_outstanding_extents(struct btrfs_inode *inode,
++ int mod)
++{
++ lockdep_assert_held(&inode->lock);
++ inode->outstanding_extents += mod;
++ if (btrfs_is_free_space_inode(&inode->vfs_inode))
++ return;
++}
++
++static inline void btrfs_mod_reserved_extents(struct btrfs_inode *inode, int mod)
++{
++ lockdep_assert_held(&inode->lock);
++ inode->reserved_extents += mod;
++ if (btrfs_is_free_space_inode(&inode->vfs_inode))
++ return;
++}
++
+ static inline int btrfs_inode_in_log(struct inode *inode, u64 generation)
+ {
+ int ret = 0;
+--- a/fs/btrfs/ctree.h
++++ b/fs/btrfs/ctree.h
+@@ -2700,6 +2700,8 @@ int btrfs_subvolume_reserve_metadata(str
+ void btrfs_subvolume_release_metadata(struct btrfs_root *root,
+ struct btrfs_block_rsv *rsv,
+ u64 qgroup_reserved);
++void btrfs_delalloc_release_extents(struct btrfs_inode *inode, u64 num_bytes);
++
+ int btrfs_delalloc_reserve_metadata(struct inode *inode, u64 num_bytes);
+ void btrfs_delalloc_release_metadata(struct inode *inode, u64 num_bytes);
+ int btrfs_delalloc_reserve_space(struct inode *inode,
+@@ -3611,4 +3613,13 @@ static inline int btrfs_test_is_dummy_ro
+ return 0;
+ }
+
++static inline int btrfs_is_testing(struct btrfs_fs_info *fs_info)
++{
++#ifdef CONFIG_BTRFS_FS_RUN_SANITY_TESTS
++ if (unlikely(test_bit(BTRFS_FS_STATE_DUMMY_FS_INFO,
++ &fs_info->fs_state)))
++ return 1;
++#endif
++ return 0;
++}
+ #endif
+--- a/fs/btrfs/extent-tree.c
++++ b/fs/btrfs/extent-tree.c
+@@ -5897,43 +5897,30 @@ void btrfs_subvolume_release_metadata(st
+ }
+
+ /**
+- * drop_outstanding_extent - drop an outstanding extent
++ * drop_over_reserved_extents - drop our extra extent reservations
+ * @inode: the inode we're dropping the extent for
+- * @num_bytes: the number of bytes we're relaseing.
+ *
+- * This is called when we are freeing up an outstanding extent, either called
+- * after an error or after an extent is written. This will return the number of
+- * reserved extents that need to be freed. This must be called with
+- * BTRFS_I(inode)->lock held.
++ * We reserve extents we may use, but they may have been merged with other
++ * extents and we may not need the extra reservation.
++ *
++ * We also call this when we've completed io to an extent or had an error and
++ * cleared the outstanding extent, in either case we no longer need our
++ * reservation and can drop the excess.
+ */
+-static unsigned drop_outstanding_extent(struct inode *inode, u64 num_bytes)
++static unsigned drop_over_reserved_extents(struct btrfs_inode *inode)
+ {
+- unsigned drop_inode_space = 0;
+- unsigned dropped_extents = 0;
+- unsigned num_extents;
++ unsigned num_extents = 0;
+
+- num_extents = count_max_extents(num_bytes);
+- ASSERT(num_extents);
+- ASSERT(BTRFS_I(inode)->outstanding_extents >= num_extents);
+- BTRFS_I(inode)->outstanding_extents -= num_extents;
+-
+- if (BTRFS_I(inode)->outstanding_extents == 0 &&
++ if (inode->reserved_extents > inode->outstanding_extents) {
++ num_extents = inode->reserved_extents -
++ inode->outstanding_extents;
++ btrfs_mod_reserved_extents(inode, -num_extents);
++ }
++ if (inode->outstanding_extents == 0 &&
+ test_and_clear_bit(BTRFS_INODE_DELALLOC_META_RESERVED,
+- &BTRFS_I(inode)->runtime_flags))
+- drop_inode_space = 1;
+-
+- /*
+- * If we have more or the same amount of outsanding extents than we have
+- * reserved then we need to leave the reserved extents count alone.
+- */
+- if (BTRFS_I(inode)->outstanding_extents >=
+- BTRFS_I(inode)->reserved_extents)
+- return drop_inode_space;
+-
+- dropped_extents = BTRFS_I(inode)->reserved_extents -
+- BTRFS_I(inode)->outstanding_extents;
+- BTRFS_I(inode)->reserved_extents -= dropped_extents;
+- return dropped_extents + drop_inode_space;
++ &inode->runtime_flags))
++ num_extents++;
++ return num_extents;
+ }
+
+ /**
+@@ -5988,13 +5975,15 @@ int btrfs_delalloc_reserve_metadata(stru
+ struct btrfs_block_rsv *block_rsv = &root->fs_info->delalloc_block_rsv;
+ u64 to_reserve = 0;
+ u64 csum_bytes;
+- unsigned nr_extents;
++ unsigned nr_extents, reserve_extents;
+ enum btrfs_reserve_flush_enum flush = BTRFS_RESERVE_FLUSH_ALL;
+ int ret = 0;
+ bool delalloc_lock = true;
+ u64 to_free = 0;
+ unsigned dropped;
+ bool release_extra = false;
++ bool underflow = false;
++ bool did_retry = false;
+
+ /* If we are a free space inode we need to not flush since we will be in
+ * the middle of a transaction commit. We also don't need the delalloc
+@@ -6019,19 +6008,31 @@ int btrfs_delalloc_reserve_metadata(stru
+ mutex_lock(&BTRFS_I(inode)->delalloc_mutex);
+
+ num_bytes = ALIGN(num_bytes, root->sectorsize);
+-
++retry:
+ spin_lock(&BTRFS_I(inode)->lock);
+- nr_extents = count_max_extents(num_bytes);
+- BTRFS_I(inode)->outstanding_extents += nr_extents;
++ reserve_extents = nr_extents = count_max_extents(num_bytes);
++ btrfs_mod_outstanding_extents(BTRFS_I(inode), nr_extents);
+
+- nr_extents = 0;
++ /*
++ * Because we add an outstanding extent for ordered before we clear
++ * delalloc we will double count our outstanding extents slightly. This
++ * could mean that we transiently over-reserve, which could result in an
++ * early ENOSPC if our timing is unlucky. Keep track of the case that
++ * we had a reservation underflow so we can retry if we fail.
++ *
++ * Keep in mind we can legitimately have more outstanding extents than
++ * reserved because of fragmentation, so only allow a retry once.
++ */
+ if (BTRFS_I(inode)->outstanding_extents >
+- BTRFS_I(inode)->reserved_extents)
+- nr_extents += BTRFS_I(inode)->outstanding_extents -
+- BTRFS_I(inode)->reserved_extents;
++ BTRFS_I(inode)->reserved_extents + nr_extents) {
++ reserve_extents = BTRFS_I(inode)->outstanding_extents -
++ BTRFS_I(inode)->reserved_extents;
++ underflow = true;
++ }
+
+ /* We always want to reserve a slot for updating the inode. */
+- to_reserve = btrfs_calc_trans_metadata_size(root, nr_extents + 1);
++ to_reserve = btrfs_calc_trans_metadata_size(root,
++ reserve_extents + 1);
+ to_reserve += calc_csum_metadata_size(inode, num_bytes, 1);
+ csum_bytes = BTRFS_I(inode)->csum_bytes;
+ spin_unlock(&BTRFS_I(inode)->lock);
+@@ -6056,7 +6057,7 @@ int btrfs_delalloc_reserve_metadata(stru
+ to_reserve -= btrfs_calc_trans_metadata_size(root, 1);
+ release_extra = true;
+ }
+- BTRFS_I(inode)->reserved_extents += nr_extents;
++ btrfs_mod_reserved_extents(BTRFS_I(inode), reserve_extents);
+ spin_unlock(&BTRFS_I(inode)->lock);
+
+ if (delalloc_lock)
+@@ -6073,7 +6074,10 @@ int btrfs_delalloc_reserve_metadata(stru
+
+ out_fail:
+ spin_lock(&BTRFS_I(inode)->lock);
+- dropped = drop_outstanding_extent(inode, num_bytes);
++ nr_extents = count_max_extents(num_bytes);
++ btrfs_mod_outstanding_extents(BTRFS_I(inode), -nr_extents);
++
++ dropped = drop_over_reserved_extents(BTRFS_I(inode));
+ /*
+ * If the inodes csum_bytes is the same as the original
+ * csum_bytes then we know we haven't raced with any free()ers
+@@ -6130,6 +6134,11 @@ out_fail:
+ trace_btrfs_space_reservation(root->fs_info, "delalloc",
+ btrfs_ino(inode), to_free, 0);
+ }
++ if (underflow && !did_retry) {
++ did_retry = true;
++ underflow = false;
++ goto retry;
++ }
+ if (delalloc_lock)
+ mutex_unlock(&BTRFS_I(inode)->delalloc_mutex);
+ return ret;
+@@ -6137,12 +6146,12 @@ out_fail:
+
+ /**
+ * btrfs_delalloc_release_metadata - release a metadata reservation for an inode
+- * @inode: the inode to release the reservation for
+- * @num_bytes: the number of bytes we're releasing
++ * @inode: the inode to release the reservation for.
++ * @num_bytes: the number of bytes we are releasing.
+ *
+ * This will release the metadata reservation for an inode. This can be called
+ * once we complete IO for a given set of bytes to release their metadata
+- * reservations.
++ * reservations, or on error for the same reason.
+ */
+ void btrfs_delalloc_release_metadata(struct inode *inode, u64 num_bytes)
+ {
+@@ -6152,8 +6161,7 @@ void btrfs_delalloc_release_metadata(str
+
+ num_bytes = ALIGN(num_bytes, root->sectorsize);
+ spin_lock(&BTRFS_I(inode)->lock);
+- dropped = drop_outstanding_extent(inode, num_bytes);
+-
++ dropped = drop_over_reserved_extents(BTRFS_I(inode));
+ if (num_bytes)
+ to_free = calc_csum_metadata_size(inode, num_bytes, 0);
+ spin_unlock(&BTRFS_I(inode)->lock);
+@@ -6171,6 +6179,43 @@ void btrfs_delalloc_release_metadata(str
+ }
+
+ /**
++ * btrfs_delalloc_release_extents - release our outstanding_extents
++ * @inode: the inode to balance the reservation for.
++ * @num_bytes: the number of bytes we originally reserved with
++ *
++ * When we reserve space we increase outstanding_extents for the extents we may
++ * add. Once we've set the range as delalloc or created our ordered extents we
++ * have outstanding_extents to track the real usage, so we use this to free our
++ * temporarily tracked outstanding_extents. This _must_ be used in conjunction
++ * with btrfs_delalloc_reserve_metadata.
++ */
++void btrfs_delalloc_release_extents(struct btrfs_inode *inode, u64 num_bytes)
++{
++ struct btrfs_fs_info *fs_info = btrfs_sb(inode->vfs_inode.i_sb);
++ unsigned num_extents;
++ u64 to_free;
++ unsigned dropped;
++
++ spin_lock(&inode->lock);
++ num_extents = count_max_extents(num_bytes);
++ btrfs_mod_outstanding_extents(inode, -num_extents);
++ dropped = drop_over_reserved_extents(inode);
++ spin_unlock(&inode->lock);
++
++ if (!dropped)
++ return;
++
++ if (btrfs_is_testing(fs_info))
++ return;
++
++ to_free = btrfs_calc_trans_metadata_size(inode->root, dropped);
++ trace_btrfs_space_reservation(fs_info, "delalloc",
++ btrfs_ino(&inode->vfs_inode),
++ to_free, 0);
++ btrfs_block_rsv_release(inode->root, &fs_info->delalloc_block_rsv, to_free);
++}
++
++/**
+ * btrfs_delalloc_reserve_space - reserve data and metadata space for
+ * delalloc
+ * @inode: inode we're writing to
+@@ -6216,10 +6261,7 @@ int btrfs_delalloc_reserve_space(struct
+ * @inode: inode we're releasing space for
+ * @start: start position of the space already reserved
+ * @len: the len of the space already reserved
+- *
+- * This must be matched with a call to btrfs_delalloc_reserve_space. This is
+- * called in the case that we don't need the metadata AND data reservations
+- * anymore. So if there is an error or we insert an inline extent.
++ * @release_bytes: the len of the space we consumed or didn't use
+ *
+ * This function will release the metadata space that was not used and will
+ * decrement ->delalloc_bytes and remove it from the fs_info delalloc_inodes
+@@ -6227,7 +6269,8 @@ int btrfs_delalloc_reserve_space(struct
+ * Also it will handle the qgroup reserved space.
+ */
+ void btrfs_delalloc_release_space(struct inode *inode,
+- struct extent_changeset *reserved, u64 start, u64 len)
++ struct extent_changeset *reserved,
++ u64 start, u64 len)
+ {
+ btrfs_delalloc_release_metadata(inode, len);
+ btrfs_free_reserved_data_space(inode, reserved, start, len);
+--- a/fs/btrfs/file.c
++++ b/fs/btrfs/file.c
+@@ -1586,6 +1586,7 @@ static noinline ssize_t __btrfs_buffered
+ }
+ }
+
++ WARN_ON(reserve_bytes == 0);
+ ret = btrfs_delalloc_reserve_metadata(inode, reserve_bytes);
+ if (ret) {
+ if (!only_release_metadata)
+@@ -1607,8 +1608,11 @@ again:
+ ret = prepare_pages(inode, pages, num_pages,
+ pos, write_bytes,
+ force_page_uptodate);
+- if (ret)
++ if (ret) {
++ btrfs_delalloc_release_extents(BTRFS_I(inode),
++ reserve_bytes);
+ break;
++ }
+
+ extents_locked = lock_and_cleanup_extent_if_need(
+ inode, pages,
+@@ -1617,6 +1621,8 @@ again:
+ if (extents_locked < 0) {
+ if (extents_locked == -EAGAIN)
+ goto again;
++ btrfs_delalloc_release_extents(BTRFS_I(inode),
++ reserve_bytes);
+ ret = extents_locked;
+ break;
+ }
+@@ -1648,25 +1654,12 @@ again:
+ PAGE_CACHE_SIZE);
+ }
+
+- /*
+- * If we had a short copy we need to release the excess delaloc
+- * bytes we reserved. We need to increment outstanding_extents
+- * because btrfs_delalloc_release_space and
+- * btrfs_delalloc_release_metadata will decrement it, but
+- * we still have an outstanding extent for the chunk we actually
+- * managed to copy.
+- */
+ if (num_sectors > dirty_sectors) {
+
+ /* release everything except the sectors we dirtied */
+ release_bytes -= dirty_sectors <<
+ root->fs_info->sb->s_blocksize_bits;
+
+- if (copied > 0) {
+- spin_lock(&BTRFS_I(inode)->lock);
+- BTRFS_I(inode)->outstanding_extents++;
+- spin_unlock(&BTRFS_I(inode)->lock);
+- }
+ if (only_release_metadata) {
+ btrfs_delalloc_release_metadata(inode,
+ release_bytes);
+@@ -1692,6 +1685,7 @@ again:
+ unlock_extent_cached(&BTRFS_I(inode)->io_tree,
+ lockstart, lockend, &cached_state,
+ GFP_NOFS);
++ btrfs_delalloc_release_extents(BTRFS_I(inode), reserve_bytes);
+ if (ret) {
+ btrfs_drop_pages(pages, num_pages);
+ break;
+--- a/fs/btrfs/inode-map.c
++++ b/fs/btrfs/inode-map.c
+@@ -499,11 +499,12 @@ again:
+ ret = btrfs_prealloc_file_range_trans(inode, trans, 0, 0, prealloc,
+ prealloc, prealloc, &alloc_hint);
+ if (ret) {
+- btrfs_delalloc_release_metadata(inode, prealloc);
++ btrfs_delalloc_release_extents(BTRFS_I(inode), prealloc);
+ goto out_put;
+ }
+
+ ret = btrfs_write_out_ino_cache(root, trans, path, inode);
++ btrfs_delalloc_release_extents(BTRFS_I(inode), prealloc);
+ out_put:
+ iput(inode);
+ out_release:
+--- a/fs/btrfs/inode.c
++++ b/fs/btrfs/inode.c
+@@ -68,7 +68,6 @@ struct btrfs_iget_args {
+ };
+
+ struct btrfs_dio_data {
+- u64 outstanding_extents;
+ u64 reserve;
+ u64 unsubmitted_oe_range_start;
+ u64 unsubmitted_oe_range_end;
+@@ -315,7 +314,6 @@ static noinline int cow_file_range_inlin
+ }
+
+ set_bit(BTRFS_INODE_NEEDS_FULL_SYNC, &BTRFS_I(inode)->runtime_flags);
+- btrfs_delalloc_release_metadata(inode, end + 1 - start);
+ btrfs_drop_extent_cache(inode, start, aligned_end - 1, 0);
+ out:
+ /*
+@@ -549,16 +547,20 @@ cont:
+ }
+ if (ret <= 0) {
+ unsigned long clear_flags = EXTENT_DELALLOC |
+- EXTENT_DEFRAG;
++ EXTENT_DEFRAG | EXTENT_DO_ACCOUNTING;
+ unsigned long page_error_op;
+
+- clear_flags |= (ret < 0) ? EXTENT_DO_ACCOUNTING : 0;
+ page_error_op = ret < 0 ? PAGE_SET_ERROR : 0;
+
+ /*
+ * inline extent creation worked or returned error,
+ * we don't need to create any more async work items.
+ * Unlock and free up our temp pages.
++ *
++ * We use DO_ACCOUNTING here because we need the
++ * delalloc_release_metadata to be done _after_ we drop
++ * our outstanding extent for clearing delalloc for this
++ * range.
+ */
+ extent_clear_unlock_delalloc(inode, start, end, end,
+ NULL, clear_flags,
+@@ -567,8 +569,6 @@ cont:
+ PAGE_SET_WRITEBACK |
+ page_error_op |
+ PAGE_END_WRITEBACK);
+- btrfs_free_reserved_data_space_noquota(inode, start,
+- end - start + 1);
+ goto free_pages_out;
+ }
+ }
+@@ -975,15 +975,19 @@ static noinline int cow_file_range(struc
+ ret = cow_file_range_inline(root, inode, start, end, 0, 0,
+ NULL);
+ if (ret == 0) {
++ /*
++ * We use DO_ACCOUNTING here because we need the
++ * delalloc_release_metadata to be run _after_ we drop
++ * our outstanding extent for clearing delalloc for this
++ * range.
++ */
+ extent_clear_unlock_delalloc(inode, start, end,
+ delalloc_end, NULL,
+ EXTENT_LOCKED | EXTENT_DELALLOC |
+- EXTENT_DEFRAG, PAGE_UNLOCK |
+- PAGE_CLEAR_DIRTY | PAGE_SET_WRITEBACK |
+- PAGE_END_WRITEBACK);
++ EXTENT_DEFRAG | EXTENT_DO_ACCOUNTING,
++ PAGE_UNLOCK | PAGE_CLEAR_DIRTY |
++ PAGE_SET_WRITEBACK | PAGE_END_WRITEBACK);
+
+- btrfs_free_reserved_data_space_noquota(inode, start,
+- end - start + 1);
+ *nr_written = *nr_written +
+ (end - start + PAGE_CACHE_SIZE) / PAGE_CACHE_SIZE;
+ *page_started = 1;
+@@ -1651,7 +1655,7 @@ static void btrfs_split_extent_hook(stru
+ }
+
+ spin_lock(&BTRFS_I(inode)->lock);
+- BTRFS_I(inode)->outstanding_extents++;
++ btrfs_mod_outstanding_extents(BTRFS_I(inode), 1);
+ spin_unlock(&BTRFS_I(inode)->lock);
+ }
+
+@@ -1680,7 +1684,7 @@ static void btrfs_merge_extent_hook(stru
+ /* we're not bigger than the max, unreserve the space and go */
+ if (new_size <= BTRFS_MAX_EXTENT_SIZE) {
+ spin_lock(&BTRFS_I(inode)->lock);
+- BTRFS_I(inode)->outstanding_extents--;
++ btrfs_mod_outstanding_extents(BTRFS_I(inode), -1);
+ spin_unlock(&BTRFS_I(inode)->lock);
+ return;
+ }
+@@ -1711,7 +1715,7 @@ static void btrfs_merge_extent_hook(stru
+ return;
+
+ spin_lock(&BTRFS_I(inode)->lock);
+- BTRFS_I(inode)->outstanding_extents--;
++ btrfs_mod_outstanding_extents(BTRFS_I(inode), -1);
+ spin_unlock(&BTRFS_I(inode)->lock);
+ }
+
+@@ -1774,15 +1778,12 @@ static void btrfs_set_bit_hook(struct in
+ if (!(state->state & EXTENT_DELALLOC) && (*bits & EXTENT_DELALLOC)) {
+ struct btrfs_root *root = BTRFS_I(inode)->root;
+ u64 len = state->end + 1 - state->start;
++ u32 num_extents = count_max_extents(len);
+ bool do_list = !btrfs_is_free_space_inode(inode);
+
+- if (*bits & EXTENT_FIRST_DELALLOC) {
+- *bits &= ~EXTENT_FIRST_DELALLOC;
+- } else {
+- spin_lock(&BTRFS_I(inode)->lock);
+- BTRFS_I(inode)->outstanding_extents++;
+- spin_unlock(&BTRFS_I(inode)->lock);
+- }
++ spin_lock(&BTRFS_I(inode)->lock);
++ btrfs_mod_outstanding_extents(BTRFS_I(inode), num_extents);
++ spin_unlock(&BTRFS_I(inode)->lock);
+
+ /* For sanity tests */
+ if (btrfs_test_is_dummy_root(root))
+@@ -1825,13 +1826,9 @@ static void btrfs_clear_bit_hook(struct
+ struct btrfs_root *root = BTRFS_I(inode)->root;
+ bool do_list = !btrfs_is_free_space_inode(inode);
+
+- if (*bits & EXTENT_FIRST_DELALLOC) {
+- *bits &= ~EXTENT_FIRST_DELALLOC;
+- } else if (!(*bits & EXTENT_CLEAR_META_RESV)) {
+- spin_lock(&BTRFS_I(inode)->lock);
+- BTRFS_I(inode)->outstanding_extents -= num_extents;
+- spin_unlock(&BTRFS_I(inode)->lock);
+- }
++ spin_lock(&BTRFS_I(inode)->lock);
++ btrfs_mod_outstanding_extents(BTRFS_I(inode), -num_extents);
++ spin_unlock(&BTRFS_I(inode)->lock);
+
+ /*
+ * We don't reserve metadata space for space cache inodes so we
+@@ -2099,6 +2096,7 @@ again:
+
+ ClearPageChecked(page);
+ set_page_dirty(page);
++ btrfs_delalloc_release_extents(BTRFS_I(inode), PAGE_SIZE);
+ out:
+ unlock_extent_cached(&BTRFS_I(inode)->io_tree, page_start, page_end,
+ &cached_state, GFP_NOFS);
+@@ -3035,8 +3033,6 @@ out_unlock:
+ ordered_extent->file_offset +
+ ordered_extent->len - 1, &cached_state, GFP_NOFS);
+ out:
+- if (root != root->fs_info->tree_root)
+- btrfs_delalloc_release_metadata(inode, ordered_extent->len);
+ if (trans)
+ btrfs_end_transaction(trans, root);
+
+@@ -4769,8 +4765,11 @@ int btrfs_truncate_block(struct inode *i
+ (!len || ((len & (blocksize - 1)) == 0)))
+ goto out;
+
++ block_start = round_down(from, blocksize);
++ block_end = block_start + blocksize - 1;
++
+ ret = btrfs_delalloc_reserve_space(inode, &data_reserved,
+- round_down(from, blocksize), blocksize);
++ block_start, blocksize);
+ if (ret)
+ goto out;
+
+@@ -4778,15 +4777,12 @@ again:
+ page = find_or_create_page(mapping, index, mask);
+ if (!page) {
+ btrfs_delalloc_release_space(inode, data_reserved,
+- round_down(from, blocksize),
+- blocksize);
++ block_start, blocksize);
++ btrfs_delalloc_release_extents(BTRFS_I(inode), blocksize);
+ ret = -ENOMEM;
+ goto out;
+ }
+
+- block_start = round_down(from, blocksize);
+- block_end = block_start + blocksize - 1;
+-
+ if (!PageUptodate(page)) {
+ ret = btrfs_readpage(NULL, page);
+ lock_page(page);
+@@ -4851,6 +4847,7 @@ out_unlock:
+ if (ret)
+ btrfs_delalloc_release_space(inode, data_reserved, block_start,
+ blocksize);
++ btrfs_delalloc_release_extents(BTRFS_I(inode), blocksize);
+ unlock_page(page);
+ page_cache_release(page);
+ out:
+@@ -7638,33 +7635,6 @@ static struct extent_map *create_pinned_
+ return em;
+ }
+
+-static void adjust_dio_outstanding_extents(struct inode *inode,
+- struct btrfs_dio_data *dio_data,
+- const u64 len)
+-{
+- unsigned num_extents = count_max_extents(len);
+-
+- /*
+- * If we have an outstanding_extents count still set then we're
+- * within our reservation, otherwise we need to adjust our inode
+- * counter appropriately.
+- */
+- if (dio_data->outstanding_extents >= num_extents) {
+- dio_data->outstanding_extents -= num_extents;
+- } else {
+- /*
+- * If dio write length has been split due to no large enough
+- * contiguous space, we need to compensate our inode counter
+- * appropriately.
+- */
+- u64 num_needed = num_extents - dio_data->outstanding_extents;
+-
+- spin_lock(&BTRFS_I(inode)->lock);
+- BTRFS_I(inode)->outstanding_extents += num_needed;
+- spin_unlock(&BTRFS_I(inode)->lock);
+- }
+-}
+-
+ static int btrfs_get_blocks_direct(struct inode *inode, sector_t iblock,
+ struct buffer_head *bh_result, int create)
+ {
+@@ -7826,7 +7796,6 @@ unlock:
+ if (start + len > i_size_read(inode))
+ i_size_write(inode, start + len);
+
+- adjust_dio_outstanding_extents(inode, dio_data, len);
+ WARN_ON(dio_data->reserve < len);
+ dio_data->reserve -= len;
+ dio_data->unsubmitted_oe_range_end = start + len;
+@@ -7856,14 +7825,6 @@ unlock_err:
+ err:
+ if (dio_data)
+ current->journal_info = dio_data;
+- /*
+- * Compensate the delalloc release we do in btrfs_direct_IO() when we
+- * write less data then expected, so that we don't underflow our inode's
+- * outstanding extents counter.
+- */
+- if (create && dio_data)
+- adjust_dio_outstanding_extents(inode, dio_data, len);
+-
+ return ret;
+ }
+
+@@ -8710,7 +8671,6 @@ static ssize_t btrfs_direct_IO(struct ki
+ offset, count);
+ if (ret)
+ goto out;
+- dio_data.outstanding_extents = count_max_extents(count);
+
+ /*
+ * We need to know how many extents we reserved so that we can
+@@ -8734,6 +8694,7 @@ static ssize_t btrfs_direct_IO(struct ki
+ btrfs_submit_direct, flags);
+ if (iov_iter_rw(iter) == WRITE) {
+ current->journal_info = NULL;
++ btrfs_delalloc_release_extents(BTRFS_I(inode), count);
+ if (ret < 0 && ret != -EIOCBQUEUED) {
+ if (dio_data.reserve)
+ btrfs_delalloc_release_space(inode, data_reserved,
+@@ -9068,9 +9029,6 @@ again:
+ reserved_space = round_up(size - page_start, root->sectorsize);
+ if (reserved_space < PAGE_CACHE_SIZE) {
+ end = page_start + reserved_space - 1;
+- spin_lock(&BTRFS_I(inode)->lock);
+- BTRFS_I(inode)->outstanding_extents++;
+- spin_unlock(&BTRFS_I(inode)->lock);
+ btrfs_delalloc_release_space(inode, data_reserved,
+ page_start, PAGE_CACHE_SIZE - reserved_space);
+ }
+@@ -9122,12 +9080,14 @@ again:
+
+ out_unlock:
+ if (!ret) {
++ btrfs_delalloc_release_extents(BTRFS_I(inode), PAGE_SIZE);
+ sb_end_pagefault(inode->i_sb);
+ extent_changeset_free(data_reserved);
+ return VM_FAULT_LOCKED;
+ }
+ unlock_page(page);
+ out:
++ btrfs_delalloc_release_extents(BTRFS_I(inode), PAGE_SIZE);
+ btrfs_delalloc_release_space(inode, data_reserved, page_start,
+ reserved_space);
+ out_noreserve:
+--- a/fs/btrfs/ioctl.c
++++ b/fs/btrfs/ioctl.c
+@@ -1251,6 +1251,7 @@ again:
+ unlock_page(pages[i]);
+ page_cache_release(pages[i]);
+ }
++ btrfs_delalloc_release_extents(BTRFS_I(inode), page_cnt << PAGE_SHIFT);
+ extent_changeset_free(data_reserved);
+ return i_done;
+ out:
+@@ -1261,6 +1262,7 @@ out:
+ btrfs_delalloc_release_space(inode, data_reserved,
+ start_index << PAGE_CACHE_SHIFT,
+ page_cnt << PAGE_CACHE_SHIFT);
++ btrfs_delalloc_release_extents(BTRFS_I(inode), page_cnt << PAGE_SHIFT);
+ extent_changeset_free(data_reserved);
+ return ret;
+
+--- a/fs/btrfs/ordered-data.c
++++ b/fs/btrfs/ordered-data.c
+@@ -241,6 +241,15 @@ static int __btrfs_add_ordered_extent(st
+ }
+ spin_unlock(&root->ordered_extent_lock);
+
++ /*
++ * We don't need the count_max_extents here, we can assume that all of
++ * that work has been done at higher layers, so this is truly the
++ * smallest the extent is going to get.
++ */
++ spin_lock(&BTRFS_I(inode)->lock);
++ btrfs_mod_outstanding_extents(BTRFS_I(inode), 1);
++ spin_unlock(&BTRFS_I(inode)->lock);
++
+ return 0;
+ }
+
+@@ -588,11 +597,19 @@ void btrfs_remove_ordered_extent(struct
+ struct btrfs_ordered_extent *entry)
+ {
+ struct btrfs_ordered_inode_tree *tree;
+- struct btrfs_root *root = BTRFS_I(inode)->root;
++ struct btrfs_inode *btrfs_inode = BTRFS_I(inode);
++ struct btrfs_root *root = btrfs_inode->root;
+ struct rb_node *node;
+ bool dec_pending_ordered = false;
+
+- tree = &BTRFS_I(inode)->ordered_tree;
++ /* This is paired with btrfs_add_ordered_extent. */
++ spin_lock(&btrfs_inode->lock);
++ btrfs_mod_outstanding_extents(btrfs_inode, -1);
++ spin_unlock(&btrfs_inode->lock);
++ if (root != root->fs_info->tree_root)
++ btrfs_delalloc_release_metadata(inode, entry->len);
++
++ tree = &btrfs_inode->ordered_tree;
+ spin_lock_irq(&tree->lock);
+ node = &entry->rb_node;
+ rb_erase(node, &tree->tree);
+--- a/fs/btrfs/relocation.c
++++ b/fs/btrfs/relocation.c
+@@ -3251,6 +3251,8 @@ static int relocate_file_extent_cluster(
+ page_cache_release(page);
+ btrfs_delalloc_release_metadata(inode,
+ PAGE_CACHE_SIZE);
++ btrfs_delalloc_release_extents(BTRFS_I(inode),
++ PAGE_SIZE);
+ ret = -EIO;
+ goto out;
+ }
+@@ -3280,6 +3282,7 @@ static int relocate_file_extent_cluster(
+ page_cache_release(page);
+
+ index++;
++ btrfs_delalloc_release_extents(BTRFS_I(inode), PAGE_SIZE);
+ balance_dirty_pages_ratelimited(inode->i_mapping);
+ btrfs_throttle(BTRFS_I(inode)->root);
+ }
+--- a/fs/btrfs/tests/inode-tests.c
++++ b/fs/btrfs/tests/inode-tests.c
+@@ -939,7 +939,6 @@ static int test_extent_accounting(void)
+ btrfs_test_inode_set_ops(inode);
+
+ /* [BTRFS_MAX_EXTENT_SIZE] */
+- BTRFS_I(inode)->outstanding_extents++;
+ ret = btrfs_set_extent_delalloc(inode, 0, BTRFS_MAX_EXTENT_SIZE - 1,
+ NULL, 0);
+ if (ret) {
+@@ -954,7 +953,6 @@ static int test_extent_accounting(void)
+ }
+
+ /* [BTRFS_MAX_EXTENT_SIZE][4k] */
+- BTRFS_I(inode)->outstanding_extents++;
+ ret = btrfs_set_extent_delalloc(inode, BTRFS_MAX_EXTENT_SIZE,
+ BTRFS_MAX_EXTENT_SIZE + 4095, NULL, 0);
+ if (ret) {
+@@ -973,7 +971,7 @@ static int test_extent_accounting(void)
+ BTRFS_MAX_EXTENT_SIZE >> 1,
+ (BTRFS_MAX_EXTENT_SIZE >> 1) + 4095,
+ EXTENT_DELALLOC | EXTENT_DIRTY |
+- EXTENT_UPTODATE | EXTENT_DO_ACCOUNTING, 0, 0,
++ EXTENT_UPTODATE, 0, 0,
+ NULL, GFP_NOFS);
+ if (ret) {
+ test_msg("clear_extent_bit returned %d\n", ret);
+@@ -987,7 +985,6 @@ static int test_extent_accounting(void)
+ }
+
+ /* [BTRFS_MAX_EXTENT_SIZE][4K] */
+- BTRFS_I(inode)->outstanding_extents++;
+ ret = btrfs_set_extent_delalloc(inode, BTRFS_MAX_EXTENT_SIZE >> 1,
+ (BTRFS_MAX_EXTENT_SIZE >> 1) + 4095,
+ NULL, 0);
+@@ -1004,12 +1001,7 @@ static int test_extent_accounting(void)
+
+ /*
+ * [BTRFS_MAX_EXTENT_SIZE+4K][4K HOLE][BTRFS_MAX_EXTENT_SIZE+4K]
+- *
+- * I'm artificially adding 2 to outstanding_extents because in the
+- * buffered IO case we'd add things up as we go, but I don't feel like
+- * doing that here, this isn't the interesting case we want to test.
+ */
+- BTRFS_I(inode)->outstanding_extents += 2;
+ ret = btrfs_set_extent_delalloc(inode, BTRFS_MAX_EXTENT_SIZE + 8192,
+ (BTRFS_MAX_EXTENT_SIZE << 1) + 12287,
+ NULL, 0);
+@@ -1044,7 +1036,7 @@ static int test_extent_accounting(void)
+ BTRFS_MAX_EXTENT_SIZE+4096,
+ BTRFS_MAX_EXTENT_SIZE+8191,
+ EXTENT_DIRTY | EXTENT_DELALLOC |
+- EXTENT_DO_ACCOUNTING | EXTENT_UPTODATE, 0, 0,
++ EXTENT_UPTODATE, 0, 0,
+ NULL, GFP_NOFS);
+ if (ret) {
+ test_msg("clear_extent_bit returned %d\n", ret);
+@@ -1061,7 +1053,6 @@ static int test_extent_accounting(void)
+ * Refill the hole again just for good measure, because I thought it
+ * might fail and I'd rather satisfy my paranoia at this point.
+ */
+- BTRFS_I(inode)->outstanding_extents++;
+ ret = btrfs_set_extent_delalloc(inode, BTRFS_MAX_EXTENT_SIZE+4096,
+ BTRFS_MAX_EXTENT_SIZE+8191, NULL, 0);
+ if (ret) {
+@@ -1078,7 +1069,7 @@ static int test_extent_accounting(void)
+ /* Empty */
+ ret = clear_extent_bit(&BTRFS_I(inode)->io_tree, 0, (u64)-1,
+ EXTENT_DIRTY | EXTENT_DELALLOC |
+- EXTENT_DO_ACCOUNTING | EXTENT_UPTODATE, 0, 0,
++ EXTENT_UPTODATE, 0, 0,
+ NULL, GFP_NOFS);
+ if (ret) {
+ test_msg("clear_extent_bit returned %d\n", ret);
+@@ -1095,7 +1086,7 @@ out:
+ if (ret)
+ clear_extent_bit(&BTRFS_I(inode)->io_tree, 0, (u64)-1,
+ EXTENT_DIRTY | EXTENT_DELALLOC |
+- EXTENT_DO_ACCOUNTING | EXTENT_UPTODATE, 0, 0,
++ EXTENT_UPTODATE, 0, 0,
+ NULL, GFP_NOFS);
+ iput(inode);
+ btrfs_free_dummy_root(root);
diff --git a/patches.suse/0018-btrfs-add-tracepoints-for-outstanding-extents-mods.patch b/patches.suse/0018-btrfs-add-tracepoints-for-outstanding-extents-mods.patch
new file mode 100644
index 0000000000..153778d0d7
--- /dev/null
+++ b/patches.suse/0018-btrfs-add-tracepoints-for-outstanding-extents-mods.patch
@@ -0,0 +1,61 @@
+From dd48d4072e0cdac51edcbff66342fe2f21b5b588 Mon Sep 17 00:00:00 2001
+From: Josef Bacik <josef@toxicpanda.com>
+Date: Thu, 19 Oct 2017 14:15:56 -0400
+Patch-mainline: v4.15
+Git-commit: dd48d4072e0cdac51edcbff66342fe2f21b5b588
+References: dependency for bsc#1031392
+Subject: [PATCH 18/24] btrfs: add tracepoints for outstanding extents mods
+
+This is handy for tracing problems with modifying the outstanding
+extents counters.
+
+Signed-off-by: Josef Bacik <jbacik@fb.com>
+Signed-off-by: David Sterba <dsterba@suse.com>
+Signed-off-by: Qu Wenruo <wqu@suse.com>
+---
+ fs/btrfs/btrfs_inode.h | 3 +++
+ include/trace/events/btrfs.h | 21 +++++++++++++++++++++
+ 2 files changed, 24 insertions(+)
+
+--- a/fs/btrfs/btrfs_inode.h
++++ b/fs/btrfs/btrfs_inode.h
+@@ -270,6 +270,9 @@ static inline void btrfs_mod_reserved_ex
+ inode->reserved_extents += mod;
+ if (btrfs_is_free_space_inode(&inode->vfs_inode))
+ return;
++ trace_btrfs_inode_mod_outstanding_extents(inode->root,
++ btrfs_ino(&inode->vfs_inode),
++ mod);
+ }
+
+ static inline int btrfs_inode_in_log(struct inode *inode, u64 generation)
+--- a/include/trace/events/btrfs.h
++++ b/include/trace/events/btrfs.h
+@@ -1595,6 +1595,27 @@ TRACE_EVENT(qgroup_meta_reserve,
+ show_root_type(__entry->refroot), __entry->diff)
+ );
+
++TRACE_EVENT(btrfs_inode_mod_outstanding_extents,
++ TP_PROTO(struct btrfs_root *root, u64 ino, int mod),
++
++ TP_ARGS(root, ino, mod),
++
++ TP_STRUCT__entry_btrfs(
++ __field( u64, root_objectid )
++ __field( u64, ino )
++ __field( int, mod )
++ ),
++
++ TP_fast_assign_btrfs(root->fs_info,
++ __entry->root_objectid = root->objectid;
++ __entry->ino = ino;
++ __entry->mod = mod;
++ ),
++
++ TP_printk_btrfs("root=%llu(%s) ino=%llu mod=%d",
++ show_root_type(__entry->root_objectid),
++ (unsigned long long)__entry->ino, __entry->mod)
++);
+ #endif /* _TRACE_BTRFS_H */
+
+ /* This part must be outside protection */
diff --git a/patches.suse/0019-btrfs-make-the-delalloc-block-rsv-per-inode.patch b/patches.suse/0019-btrfs-make-the-delalloc-block-rsv-per-inode.patch
new file mode 100644
index 0000000000..13ab0c1094
--- /dev/null
+++ b/patches.suse/0019-btrfs-make-the-delalloc-block-rsv-per-inode.patch
@@ -0,0 +1,800 @@
+From 69fe2d75dd91d0124ad2ab6e9fef07633bd730e0 Mon Sep 17 00:00:00 2001
+From: Josef Bacik <josef@toxicpanda.com>
+Date: Thu, 19 Oct 2017 14:15:57 -0400
+Patch-mainline: v4.15
+Git-commit: 69fe2d75dd91d0124ad2ab6e9fef07633bd730e0
+References: dependency for bsc#1031392
+Subject: [PATCH] btrfs: make the delalloc block rsv per inode
+
+The way we handle delalloc metadata reservations has gotten
+progressively more complicated over the years. There is so much cruft
+and weirdness around keeping the reserved count and outstanding counters
+consistent and handling the error cases that it's impossible to
+understand.
+
+Fix this by making the delalloc block rsv per-inode. This way we can
+calculate the actual size of the outstanding metadata reservations every
+time we make a change, and then reserve the delta based on that amount.
+This greatly simplifies the code everywhere, and makes the error
+handling in btrfs_delalloc_reserve_metadata far less terrifying.
+
+Signed-off-by: Josef Bacik <jbacik@fb.com>
+Signed-off-by: David Sterba <dsterba@suse.com>
+---
+ fs/btrfs/btrfs_inode.h | 29 +---
+ fs/btrfs/ctree.h | 5
+ fs/btrfs/delayed-inode.c | 47 ------
+ fs/btrfs/disk-io.c | 18 +-
+ fs/btrfs/extent-tree.c | 328 ++++++++++++++++-------------------------------
+ fs/btrfs/inode.c | 18 +-
+ 6 files changed, 144 insertions(+), 301 deletions(-)
+
+--- a/fs/btrfs/btrfs_inode.h
++++ b/fs/btrfs/btrfs_inode.h
+@@ -36,14 +36,13 @@
+ #define BTRFS_INODE_ORPHAN_META_RESERVED 1
+ #define BTRFS_INODE_DUMMY 2
+ #define BTRFS_INODE_IN_DEFRAG 3
+-#define BTRFS_INODE_DELALLOC_META_RESERVED 4
+-#define BTRFS_INODE_HAS_ORPHAN_ITEM 5
+-#define BTRFS_INODE_HAS_ASYNC_EXTENT 6
+-#define BTRFS_INODE_NEEDS_FULL_SYNC 7
+-#define BTRFS_INODE_COPY_EVERYTHING 8
+-#define BTRFS_INODE_IN_DELALLOC_LIST 9
+-#define BTRFS_INODE_READDIO_NEED_LOCK 10
+-#define BTRFS_INODE_HAS_PROPS 11
++#define BTRFS_INODE_HAS_ORPHAN_ITEM 4
++#define BTRFS_INODE_HAS_ASYNC_EXTENT 5
++#define BTRFS_INODE_NEEDS_FULL_SYNC 6
++#define BTRFS_INODE_COPY_EVERYTHING 7
++#define BTRFS_INODE_IN_DELALLOC_LIST 8
++#define BTRFS_INODE_READDIO_NEED_LOCK 9
++#define BTRFS_INODE_HAS_PROPS 10
+
+ /* in memory btrfs inode */
+ struct btrfs_inode {
+@@ -169,7 +168,8 @@ struct btrfs_inode {
+ * of extent items we've reserved metadata for.
+ */
+ unsigned outstanding_extents;
+- unsigned reserved_extents;
++
++ struct btrfs_block_rsv block_rsv;
+
+ /*
+ * always compress this one file
+@@ -264,17 +264,6 @@ static inline void btrfs_mod_outstanding
+ return;
+ }
+
+-static inline void btrfs_mod_reserved_extents(struct btrfs_inode *inode, int mod)
+-{
+- lockdep_assert_held(&inode->lock);
+- inode->reserved_extents += mod;
+- if (btrfs_is_free_space_inode(&inode->vfs_inode))
+- return;
+- trace_btrfs_inode_mod_outstanding_extents(inode->root,
+- btrfs_ino(&inode->vfs_inode),
+- mod);
+-}
+-
+ static inline int btrfs_inode_in_log(struct inode *inode, u64 generation)
+ {
+ int ret = 0;
+--- a/fs/btrfs/ctree.h
++++ b/fs/btrfs/ctree.h
+@@ -719,8 +719,6 @@ struct btrfs_fs_info {
+ * delayed dir index item
+ */
+ struct btrfs_block_rsv global_block_rsv;
+- /* block reservation for delay allocation */
+- struct btrfs_block_rsv delalloc_block_rsv;
+ /* block reservation for metadata operations */
+ struct btrfs_block_rsv trans_block_rsv;
+ /* block reservation for chunk tree */
+@@ -2709,6 +2707,9 @@ int btrfs_delalloc_reserve_space(struct
+ void btrfs_init_block_rsv(struct btrfs_block_rsv *rsv, unsigned short type);
+ struct btrfs_block_rsv *btrfs_alloc_block_rsv(struct btrfs_root *root,
+ unsigned short type);
++void btrfs_init_metadata_block_rsv(struct btrfs_fs_info *fs_info,
++ struct btrfs_block_rsv *rsv,
++ unsigned short type);
+ void btrfs_free_block_rsv(struct btrfs_root *root,
+ struct btrfs_block_rsv *rsv);
+ void __btrfs_free_block_rsv(struct btrfs_block_rsv *rsv);
+--- a/fs/btrfs/delayed-inode.c
++++ b/fs/btrfs/delayed-inode.c
+@@ -596,7 +596,6 @@ static int btrfs_delayed_inode_reserve_m
+ struct btrfs_block_rsv *dst_rsv;
+ u64 num_bytes;
+ int ret;
+- bool release = false;
+
+ src_rsv = trans->block_rsv;
+ dst_rsv = &root->fs_info->delayed_block_rsv;
+@@ -604,36 +603,13 @@ static int btrfs_delayed_inode_reserve_m
+ num_bytes = btrfs_calc_trans_metadata_size(root, 1);
+
+ /*
+- * If our block_rsv is the delalloc block reserve then check and see if
+- * we have our extra reservation for updating the inode. If not fall
+- * through and try to reserve space quickly.
+- *
+- * We used to try and steal from the delalloc block rsv or the global
+- * reserve, but we'd steal a full reservation, which isn't kind. We are
+- * here through delalloc which means we've likely just cowed down close
+- * to the leaf that contains the inode, so we would steal less just
+- * doing the fallback inode update, so if we do end up having to steal
+- * from the global block rsv we hopefully only steal one or two blocks
+- * worth which is less likely to hurt us.
+- */
+- if (src_rsv && src_rsv->type == BTRFS_BLOCK_RSV_DELALLOC) {
+- spin_lock(&BTRFS_I(inode)->lock);
+- if (test_and_clear_bit(BTRFS_INODE_DELALLOC_META_RESERVED,
+- &BTRFS_I(inode)->runtime_flags))
+- release = true;
+- else
+- src_rsv = NULL;
+- spin_unlock(&BTRFS_I(inode)->lock);
+- }
+-
+- /*
+ * btrfs_dirty_inode will update the inode under btrfs_join_transaction
+ * which doesn't reserve space for speed. This is a problem since we
+ * still need to reserve space for this update, so try to reserve the
+ * space.
+ *
+ * Now if src_rsv == delalloc_block_rsv we'll let it just steal since
+- * we're accounted for.
++ * we always reserve enough to update the inode item.
+ */
+ if (!src_rsv || (!trans->bytes_reserved &&
+ src_rsv->type != BTRFS_BLOCK_RSV_DELALLOC)) {
+@@ -658,32 +634,11 @@ static int btrfs_delayed_inode_reserve_m
+ }
+
+ ret = btrfs_block_rsv_migrate(src_rsv, dst_rsv, num_bytes, 1);
+-
+- /*
+- * Migrate only takes a reservation, it doesn't touch the size of the
+- * block_rsv. This is to simplify people who don't normally have things
+- * migrated from their block rsv. If they go to release their
+- * reservation, that will decrease the size as well, so if migrate
+- * reduced size we'd end up with a negative size. But for the
+- * delalloc_meta_reserved stuff we will only know to drop 1 reservation,
+- * but we could in fact do this reserve/migrate dance several times
+- * between the time we did the original reservation and we'd clean it
+- * up. So to take care of this, release the space for the meta
+- * reservation here. I think it may be time for a documentation page on
+- * how block rsvs. work.
+- */
+ if (!ret) {
+ trace_btrfs_space_reservation(root->fs_info, "delayed_inode",
+ btrfs_ino(inode), num_bytes, 1);
+ node->bytes_reserved = num_bytes;
+ }
+-
+- if (release) {
+- trace_btrfs_space_reservation(root->fs_info, "delalloc",
+- btrfs_ino(inode), num_bytes, 0);
+- btrfs_block_rsv_release(root, src_rsv, num_bytes);
+- }
+-
+ return ret;
+ }
+
+--- a/fs/btrfs/disk-io.c
++++ b/fs/btrfs/disk-io.c
+@@ -2562,14 +2562,6 @@ int open_ctree(struct super_block *sb,
+ goto fail_delalloc_bytes;
+ }
+
+- fs_info->btree_inode = new_inode(sb);
+- if (!fs_info->btree_inode) {
+- err = -ENOMEM;
+- goto fail_bio_counter;
+- }
+-
+- mapping_set_gfp_mask(fs_info->btree_inode->i_mapping, GFP_NOFS);
+-
+ INIT_RADIX_TREE(&fs_info->fs_roots_radix, GFP_ATOMIC);
+ INIT_RADIX_TREE(&fs_info->buffer_radix, GFP_ATOMIC);
+ INIT_LIST_HEAD(&fs_info->trans_list);
+@@ -2603,8 +2595,6 @@ int open_ctree(struct super_block *sb,
+ btrfs_mapping_init(&fs_info->mapping_tree);
+ btrfs_init_block_rsv(&fs_info->global_block_rsv,
+ BTRFS_BLOCK_RSV_GLOBAL);
+- btrfs_init_block_rsv(&fs_info->delalloc_block_rsv,
+- BTRFS_BLOCK_RSV_DELALLOC);
+ btrfs_init_block_rsv(&fs_info->trans_block_rsv, BTRFS_BLOCK_RSV_TRANS);
+ btrfs_init_block_rsv(&fs_info->chunk_block_rsv, BTRFS_BLOCK_RSV_CHUNK);
+ btrfs_init_block_rsv(&fs_info->empty_block_rsv, BTRFS_BLOCK_RSV_EMPTY);
+@@ -2636,6 +2626,14 @@ int open_ctree(struct super_block *sb,
+
+ INIT_LIST_HEAD(&fs_info->ordered_roots);
+ spin_lock_init(&fs_info->ordered_root_lock);
++
++ fs_info->btree_inode = new_inode(sb);
++ if (!fs_info->btree_inode) {
++ err = -ENOMEM;
++ goto fail_bio_counter;
++ }
++ mapping_set_gfp_mask(fs_info->btree_inode->i_mapping, GFP_NOFS);
++
+ fs_info->delayed_root = kmalloc(sizeof(struct btrfs_delayed_root),
+ GFP_KERNEL);
+ if (!fs_info->delayed_root) {
+--- a/fs/btrfs/extent-tree.c
++++ b/fs/btrfs/extent-tree.c
+@@ -25,6 +25,7 @@
+ #include <linux/slab.h>
+ #include <linux/ratelimit.h>
+ #include <linux/percpu_counter.h>
++#include <linux/lockdep.h>
+ #include "hash.h"
+ #include "tree-log.h"
+ #include "disk-io.h"
+@@ -4749,7 +4750,6 @@ static inline int calc_reclaim_items_nr(
+ static void shrink_delalloc(struct btrfs_root *root, u64 to_reclaim, u64 orig,
+ bool wait_ordered)
+ {
+- struct btrfs_block_rsv *block_rsv;
+ struct btrfs_space_info *space_info;
+ struct btrfs_trans_handle *trans;
+ u64 delalloc_bytes;
+@@ -4765,8 +4765,7 @@ static void shrink_delalloc(struct btrfs
+ to_reclaim = (u64)items * EXTENT_SIZE_PER_ITEM;
+
+ trans = (struct btrfs_trans_handle *)current->journal_info;
+- block_rsv = &root->fs_info->delalloc_block_rsv;
+- space_info = block_rsv->space_info;
++ space_info = __find_space_info(root->fs_info, BTRFS_BLOCK_GROUP_METADATA);
+
+ delalloc_bytes = percpu_counter_sum_positive(
+ &root->fs_info->delalloc_bytes);
+@@ -5511,11 +5510,12 @@ again:
+ }
+ }
+
+-static void block_rsv_release_bytes(struct btrfs_fs_info *fs_info,
++static u64 block_rsv_release_bytes(struct btrfs_fs_info *fs_info,
+ struct btrfs_block_rsv *block_rsv,
+ struct btrfs_block_rsv *dest, u64 num_bytes)
+ {
+ struct btrfs_space_info *space_info = block_rsv->space_info;
++ u64 ret;
+
+ spin_lock(&block_rsv->lock);
+ if (num_bytes == (u64)-1)
+@@ -5530,6 +5530,7 @@ static void block_rsv_release_bytes(stru
+ }
+ spin_unlock(&block_rsv->lock);
+
++ ret = num_bytes;
+ if (num_bytes > 0) {
+ if (dest) {
+ spin_lock(&dest->lock);
+@@ -5549,6 +5550,7 @@ static void block_rsv_release_bytes(stru
+ space_info_add_old_bytes(fs_info, space_info,
+ num_bytes);
+ }
++ return ret;
+ }
+
+ int btrfs_block_rsv_migrate(struct btrfs_block_rsv *src,
+@@ -5572,6 +5574,15 @@ void btrfs_init_block_rsv(struct btrfs_b
+ rsv->type = type;
+ }
+
++void btrfs_init_metadata_block_rsv(struct btrfs_fs_info *fs_info,
++ struct btrfs_block_rsv *rsv,
++ unsigned short type)
++{
++ btrfs_init_block_rsv(rsv, type);
++ rsv->space_info = __find_space_info(fs_info,
++ BTRFS_BLOCK_GROUP_METADATA);
++}
++
+ struct btrfs_block_rsv *btrfs_alloc_block_rsv(struct btrfs_root *root,
+ unsigned short type)
+ {
+@@ -5582,9 +5593,7 @@ struct btrfs_block_rsv *btrfs_alloc_bloc
+ if (!block_rsv)
+ return NULL;
+
+- btrfs_init_block_rsv(block_rsv, type);
+- block_rsv->space_info = __find_space_info(fs_info,
+- BTRFS_BLOCK_GROUP_METADATA);
++ btrfs_init_metadata_block_rsv(fs_info, block_rsv, type);
+ return block_rsv;
+ }
+
+@@ -5668,6 +5677,68 @@ int btrfs_block_rsv_refill(struct btrfs_
+ return ret;
+ }
+
++/**
++ * btrfs_inode_rsv_refill - refill the inode block rsv.
++ * @inode - the inode we are refilling.
++ * @flush - the flusing restriction.
++ *
++ * Essentially the same as btrfs_block_rsv_refill, except it uses the
++ * block_rsv->size as the minimum size. We'll either refill the missing amount
++ * or return if we already have enough space. This will also handle the resreve
++ * tracepoint for the reserved amount.
++ */
++int btrfs_inode_rsv_refill(struct btrfs_inode *inode,
++ enum btrfs_reserve_flush_enum flush)
++{
++ struct btrfs_root *root = inode->root;
++ struct btrfs_block_rsv *block_rsv = &inode->block_rsv;
++ u64 num_bytes = 0;
++ int ret = -ENOSPC;
++
++ spin_lock(&block_rsv->lock);
++ if (block_rsv->reserved < block_rsv->size)
++ num_bytes = block_rsv->size - block_rsv->reserved;
++ spin_unlock(&block_rsv->lock);
++
++ if (num_bytes == 0)
++ return 0;
++
++ ret = reserve_metadata_bytes(root, block_rsv, num_bytes, flush);
++ if (!ret) {
++ block_rsv_add_bytes(block_rsv, num_bytes, 0);
++ trace_btrfs_space_reservation(root->fs_info, "delalloc",
++ btrfs_ino(&inode->vfs_inode),
++ num_bytes, 1);
++ }
++ return ret;
++}
++
++/**
++ * btrfs_inode_rsv_release - release any excessive reservation.
++ * @inode - the inode we need to release from.
++ *
++ * This is the same as btrfs_block_rsv_release, except that it handles the
++ * tracepoint for the reservation.
++ */
++void btrfs_inode_rsv_release(struct btrfs_inode *inode)
++{
++ struct btrfs_fs_info *fs_info = inode->root->fs_info;
++ struct btrfs_block_rsv *global_rsv = &fs_info->global_block_rsv;
++ struct btrfs_block_rsv *block_rsv = &inode->block_rsv;
++ u64 released = 0;
++
++ /*
++ * Since we statically set the block_rsv->size we just want to say we
++ * are releasing 0 bytes, and then we'll just get the reservation over
++ * the size free'd.
++ */
++ released = block_rsv_release_bytes(fs_info, block_rsv, global_rsv, 0);
++ if (released > 0)
++ trace_btrfs_space_reservation(fs_info, "delalloc",
++ btrfs_ino(&inode->vfs_inode),
++ released, 0);
++}
++
+ void btrfs_block_rsv_release(struct btrfs_root *root,
+ struct btrfs_block_rsv *block_rsv,
+ u64 num_bytes)
+@@ -5741,7 +5812,6 @@ static void init_global_block_rsv(struct
+
+ space_info = __find_space_info(fs_info, BTRFS_BLOCK_GROUP_METADATA);
+ fs_info->global_block_rsv.space_info = space_info;
+- fs_info->delalloc_block_rsv.space_info = space_info;
+ fs_info->trans_block_rsv.space_info = space_info;
+ fs_info->empty_block_rsv.space_info = space_info;
+ fs_info->delayed_block_rsv.space_info = space_info;
+@@ -5761,8 +5831,6 @@ static void release_global_block_rsv(str
+ {
+ block_rsv_release_bytes(fs_info, &fs_info->global_block_rsv, NULL,
+ (u64)-1);
+- WARN_ON(fs_info->delalloc_block_rsv.size > 0);
+- WARN_ON(fs_info->delalloc_block_rsv.reserved > 0);
+ WARN_ON(fs_info->trans_block_rsv.size > 0);
+ WARN_ON(fs_info->trans_block_rsv.reserved > 0);
+ WARN_ON(fs_info->chunk_block_rsv.size > 0);
+@@ -5896,94 +5964,36 @@ void btrfs_subvolume_release_metadata(st
+ btrfs_block_rsv_release(root, rsv, (u64)-1);
+ }
+
+-/**
+- * drop_over_reserved_extents - drop our extra extent reservations
+- * @inode: the inode we're dropping the extent for
+- *
+- * We reserve extents we may use, but they may have been merged with other
+- * extents and we may not need the extra reservation.
+- *
+- * We also call this when we've completed io to an extent or had an error and
+- * cleared the outstanding extent, in either case we no longer need our
+- * reservation and can drop the excess.
+- */
+-static unsigned drop_over_reserved_extents(struct btrfs_inode *inode)
++static void btrfs_calculate_inode_block_rsv_size(struct btrfs_fs_info *fs_info,
++ struct btrfs_inode *inode)
+ {
+- unsigned num_extents = 0;
+-
+- if (inode->reserved_extents > inode->outstanding_extents) {
+- num_extents = inode->reserved_extents -
+- inode->outstanding_extents;
+- btrfs_mod_reserved_extents(inode, -num_extents);
+- }
+- if (inode->outstanding_extents == 0 &&
+- test_and_clear_bit(BTRFS_INODE_DELALLOC_META_RESERVED,
+- &inode->runtime_flags))
+- num_extents++;
+- return num_extents;
+-}
++ struct btrfs_block_rsv *block_rsv = &inode->block_rsv;
++ u64 reserve_size = 0;
++ u64 csum_leaves;
++ unsigned outstanding_extents;
++
++ lockdep_assert_held(&inode->lock);
++ outstanding_extents = inode->outstanding_extents;
++ if (outstanding_extents)
++ reserve_size = btrfs_calc_trans_metadata_size(inode->root,
++ outstanding_extents + 1);
++ csum_leaves = btrfs_csum_bytes_to_leaves(inode->root,
++ inode->csum_bytes);
++ reserve_size += btrfs_calc_trans_metadata_size(inode->root,
++ csum_leaves);
+
+-/**
+- * calc_csum_metadata_size - return the amount of metada space that must be
+- * reserved/free'd for the given bytes.
+- * @inode: the inode we're manipulating
+- * @num_bytes: the number of bytes in question
+- * @reserve: 1 if we are reserving space, 0 if we are freeing space
+- *
+- * This adjusts the number of csum_bytes in the inode and then returns the
+- * correct amount of metadata that must either be reserved or freed. We
+- * calculate how many checksums we can fit into one leaf and then divide the
+- * number of bytes that will need to be checksumed by this value to figure out
+- * how many checksums will be required. If we are adding bytes then the number
+- * may go up and we will return the number of additional bytes that must be
+- * reserved. If it is going down we will return the number of bytes that must
+- * be freed.
+- *
+- * This must be called with BTRFS_I(inode)->lock held.
+- */
+-static u64 calc_csum_metadata_size(struct inode *inode, u64 num_bytes,
+- int reserve)
+-{
+- struct btrfs_root *root = BTRFS_I(inode)->root;
+- u64 old_csums, num_csums;
+-
+- if (BTRFS_I(inode)->flags & BTRFS_INODE_NODATASUM &&
+- BTRFS_I(inode)->csum_bytes == 0)
+- return 0;
+-
+- old_csums = btrfs_csum_bytes_to_leaves(root, BTRFS_I(inode)->csum_bytes);
+- if (reserve)
+- BTRFS_I(inode)->csum_bytes += num_bytes;
+- else
+- BTRFS_I(inode)->csum_bytes -= num_bytes;
+- num_csums = btrfs_csum_bytes_to_leaves(root, BTRFS_I(inode)->csum_bytes);
+-
+- /* No change, no need to reserve more */
+- if (old_csums == num_csums)
+- return 0;
+-
+- if (reserve)
+- return btrfs_calc_trans_metadata_size(root,
+- num_csums - old_csums);
+-
+- return btrfs_calc_trans_metadata_size(root, old_csums - num_csums);
++ spin_lock(&block_rsv->lock);
++ block_rsv->size = reserve_size;
++ spin_unlock(&block_rsv->lock);
+ }
+
+ int btrfs_delalloc_reserve_metadata(struct inode *inode, u64 num_bytes)
+ {
+ struct btrfs_root *root = BTRFS_I(inode)->root;
+- struct btrfs_block_rsv *block_rsv = &root->fs_info->delalloc_block_rsv;
+- u64 to_reserve = 0;
+- u64 csum_bytes;
+- unsigned nr_extents, reserve_extents;
++ unsigned nr_extents;
+ enum btrfs_reserve_flush_enum flush = BTRFS_RESERVE_FLUSH_ALL;
+ int ret = 0;
+ bool delalloc_lock = true;
+- u64 to_free = 0;
+- unsigned dropped;
+- bool release_extra = false;
+- bool underflow = false;
+- bool did_retry = false;
+
+ /* If we are a free space inode we need to not flush since we will be in
+ * the middle of a transaction commit. We also don't need the delalloc
+@@ -6008,33 +6018,14 @@ int btrfs_delalloc_reserve_metadata(stru
+ mutex_lock(&BTRFS_I(inode)->delalloc_mutex);
+
+ num_bytes = ALIGN(num_bytes, root->sectorsize);
+-retry:
++
++ /* Add our new extents and calculate the new rsv size. */
+ spin_lock(&BTRFS_I(inode)->lock);
+- reserve_extents = nr_extents = count_max_extents(num_bytes);
++ nr_extents = count_max_extents(num_bytes);
+ btrfs_mod_outstanding_extents(BTRFS_I(inode), nr_extents);
+
+- /*
+- * Because we add an outstanding extent for ordered before we clear
+- * delalloc we will double count our outstanding extents slightly. This
+- * could mean that we transiently over-reserve, which could result in an
+- * early ENOSPC if our timing is unlucky. Keep track of the case that
+- * we had a reservation underflow so we can retry if we fail.
+- *
+- * Keep in mind we can legitimately have more outstanding extents than
+- * reserved because of fragmentation, so only allow a retry once.
+- */
+- if (BTRFS_I(inode)->outstanding_extents >
+- BTRFS_I(inode)->reserved_extents + nr_extents) {
+- reserve_extents = BTRFS_I(inode)->outstanding_extents -
+- BTRFS_I(inode)->reserved_extents;
+- underflow = true;
+- }
+-
+- /* We always want to reserve a slot for updating the inode. */
+- to_reserve = btrfs_calc_trans_metadata_size(root,
+- reserve_extents + 1);
+- to_reserve += calc_csum_metadata_size(inode, num_bytes, 1);
+- csum_bytes = BTRFS_I(inode)->csum_bytes;
++ BTRFS_I(inode)->csum_bytes += num_bytes;
++ btrfs_calculate_inode_block_rsv_size(root->fs_info, BTRFS_I(inode));
+ spin_unlock(&BTRFS_I(inode)->lock);
+
+ if (test_bit(BTRFS_FS_QUOTA_ENABLED, &root->fs_info->flags)) {
+@@ -6044,32 +6035,15 @@ retry:
+ goto out_fail;
+ }
+
+- ret = btrfs_block_rsv_add(root, block_rsv, to_reserve, flush);
++ ret = btrfs_inode_rsv_refill(BTRFS_I(inode), flush);
+ if (unlikely(ret)) {
+ btrfs_qgroup_free_meta_prealloc(root,
+ nr_extents * root->nodesize);
+ goto out_fail;
+ }
+
+- spin_lock(&BTRFS_I(inode)->lock);
+- if (test_and_set_bit(BTRFS_INODE_DELALLOC_META_RESERVED,
+- &BTRFS_I(inode)->runtime_flags)) {
+- to_reserve -= btrfs_calc_trans_metadata_size(root, 1);
+- release_extra = true;
+- }
+- btrfs_mod_reserved_extents(BTRFS_I(inode), reserve_extents);
+- spin_unlock(&BTRFS_I(inode)->lock);
+-
+ if (delalloc_lock)
+ mutex_unlock(&BTRFS_I(inode)->delalloc_mutex);
+-
+- if (to_reserve)
+- trace_btrfs_space_reservation(root->fs_info, "delalloc",
+- btrfs_ino(inode), to_reserve, 1);
+- if (release_extra)
+- btrfs_block_rsv_release(root, block_rsv,
+- btrfs_calc_trans_metadata_size(root,
+- 1));
+ return 0;
+
+ out_fail:
+@@ -6077,68 +6051,10 @@ out_fail:
+ nr_extents = count_max_extents(num_bytes);
+ btrfs_mod_outstanding_extents(BTRFS_I(inode), -nr_extents);
+
+- dropped = drop_over_reserved_extents(BTRFS_I(inode));
+- /*
+- * If the inodes csum_bytes is the same as the original
+- * csum_bytes then we know we haven't raced with any free()ers
+- * so we can just reduce our inodes csum bytes and carry on.
+- */
+- if (BTRFS_I(inode)->csum_bytes == csum_bytes) {
+- calc_csum_metadata_size(inode, num_bytes, 0);
+- } else {
+- u64 orig_csum_bytes = BTRFS_I(inode)->csum_bytes;
+- u64 bytes;
+-
+- /*
+- * This is tricky, but first we need to figure out how much we
+- * free'd from any free-ers that occured during this
+- * reservation, so we reset ->csum_bytes to the csum_bytes
+- * before we dropped our lock, and then call the free for the
+- * number of bytes that were freed while we were trying our
+- * reservation.
+- */
+- bytes = csum_bytes - BTRFS_I(inode)->csum_bytes;
+- BTRFS_I(inode)->csum_bytes = csum_bytes;
+- to_free = calc_csum_metadata_size(inode, bytes, 0);
+-
+-
+- /*
+- * Now we need to see how much we would have freed had we not
+- * been making this reservation and our ->csum_bytes were not
+- * artificially inflated.
+- */
+- BTRFS_I(inode)->csum_bytes = csum_bytes - num_bytes;
+- bytes = csum_bytes - orig_csum_bytes;
+- bytes = calc_csum_metadata_size(inode, bytes, 0);
+-
+- /*
+- * Now reset ->csum_bytes to what it should be. If bytes is
+- * more than to_free then we would have free'd more space had we
+- * not had an artificially high ->csum_bytes, so we need to free
+- * the remainder. If bytes is the same or less then we don't
+- * need to do anything, the other free-ers did the correct
+- * thing.
+- */
+- BTRFS_I(inode)->csum_bytes = orig_csum_bytes - num_bytes;
+- if (bytes > to_free)
+- to_free = bytes - to_free;
+- else
+- to_free = 0;
+- }
++ BTRFS_I(inode)->csum_bytes -= num_bytes;
++ btrfs_calculate_inode_block_rsv_size(root->fs_info, BTRFS_I(inode));
+ spin_unlock(&BTRFS_I(inode)->lock);
+- if (dropped)
+- to_free += btrfs_calc_trans_metadata_size(root, dropped);
+-
+- if (to_free) {
+- btrfs_block_rsv_release(root, block_rsv, to_free);
+- trace_btrfs_space_reservation(root->fs_info, "delalloc",
+- btrfs_ino(inode), to_free, 0);
+- }
+- if (underflow && !did_retry) {
+- did_retry = true;
+- underflow = false;
+- goto retry;
+- }
++ btrfs_inode_rsv_release(BTRFS_I(inode));
+ if (delalloc_lock)
+ mutex_unlock(&BTRFS_I(inode)->delalloc_mutex);
+ return ret;
+@@ -6156,26 +6072,16 @@ out_fail:
+ void btrfs_delalloc_release_metadata(struct inode *inode, u64 num_bytes)
+ {
+ struct btrfs_root *root = BTRFS_I(inode)->root;
+- u64 to_free = 0;
+- unsigned dropped;
+
+ num_bytes = ALIGN(num_bytes, root->sectorsize);
+ spin_lock(&BTRFS_I(inode)->lock);
+- dropped = drop_over_reserved_extents(BTRFS_I(inode));
+- if (num_bytes)
+- to_free = calc_csum_metadata_size(inode, num_bytes, 0);
++ BTRFS_I(inode)->csum_bytes -= num_bytes;
++ btrfs_calculate_inode_block_rsv_size(root->fs_info, BTRFS_I(inode));
+ spin_unlock(&BTRFS_I(inode)->lock);
+- if (dropped > 0)
+- to_free += btrfs_calc_trans_metadata_size(root, dropped);
+
+ if (btrfs_test_is_dummy_root(root))
+ return;
+-
+- trace_btrfs_space_reservation(root->fs_info, "delalloc",
+- btrfs_ino(inode), to_free, 0);
+-
+- btrfs_block_rsv_release(root, &root->fs_info->delalloc_block_rsv,
+- to_free);
++ btrfs_inode_rsv_release(BTRFS_I(inode));
+ }
+
+ /**
+@@ -6193,26 +6099,16 @@ void btrfs_delalloc_release_extents(stru
+ {
+ struct btrfs_fs_info *fs_info = btrfs_sb(inode->vfs_inode.i_sb);
+ unsigned num_extents;
+- u64 to_free;
+- unsigned dropped;
+
+ spin_lock(&inode->lock);
+ num_extents = count_max_extents(num_bytes);
+ btrfs_mod_outstanding_extents(inode, -num_extents);
+- dropped = drop_over_reserved_extents(inode);
++ btrfs_calculate_inode_block_rsv_size(fs_info, inode);
+ spin_unlock(&inode->lock);
+
+- if (!dropped)
+- return;
+-
+ if (btrfs_is_testing(fs_info))
+ return;
+-
+- to_free = btrfs_calc_trans_metadata_size(inode->root, dropped);
+- trace_btrfs_space_reservation(fs_info, "delalloc",
+- btrfs_ino(&inode->vfs_inode),
+- to_free, 0);
+- btrfs_block_rsv_release(inode->root, &fs_info->delalloc_block_rsv, to_free);
++ btrfs_inode_rsv_release(inode);
+ }
+
+ /**
+--- a/fs/btrfs/inode.c
++++ b/fs/btrfs/inode.c
+@@ -43,6 +43,7 @@
+ #include <linux/blkdev.h>
+ #include <linux/posix_acl_xattr.h>
+ #include <linux/uio.h>
++#include <linux/magic.h>
+ #include "ctree.h"
+ #include "disk-io.h"
+ #include "transaction.h"
+@@ -282,7 +283,7 @@ static noinline int cow_file_range_inlin
+ btrfs_free_path(path);
+ return PTR_ERR(trans);
+ }
+- trans->block_rsv = &root->fs_info->delalloc_block_rsv;
++ trans->block_rsv = &BTRFS_I(inode)->block_rsv;
+
+ if (compressed_size && compressed_pages)
+ extent_item_size = btrfs_file_extent_calc_inline_size(
+@@ -2949,7 +2950,7 @@ static int btrfs_finish_ordered_io(struc
+ trans = NULL;
+ goto out;
+ }
+- trans->block_rsv = &root->fs_info->delalloc_block_rsv;
++ trans->block_rsv = &BTRFS_I(inode)->block_rsv;
+ ret = btrfs_update_inode_fallback(trans, root, inode);
+ if (ret) /* -ENOMEM or corruption */
+ btrfs_abort_transaction(trans, ret);
+@@ -2984,7 +2985,7 @@ static int btrfs_finish_ordered_io(struc
+ goto out_unlock;
+ }
+
+- trans->block_rsv = &root->fs_info->delalloc_block_rsv;
++ trans->block_rsv = &BTRFS_I(inode)->block_rsv;
+
+ if (test_bit(BTRFS_ORDERED_COMPRESSED, &ordered_extent->flags))
+ compress_type = ordered_extent->compress_type;
+@@ -8694,7 +8695,6 @@ static ssize_t btrfs_direct_IO(struct ki
+ btrfs_submit_direct, flags);
+ if (iov_iter_rw(iter) == WRITE) {
+ current->journal_info = NULL;
+- btrfs_delalloc_release_extents(BTRFS_I(inode), count);
+ if (ret < 0 && ret != -EIOCBQUEUED) {
+ if (dio_data.reserve)
+ btrfs_delalloc_release_space(inode, data_reserved,
+@@ -8715,6 +8715,7 @@ static ssize_t btrfs_direct_IO(struct ki
+ } else if (ret >= 0 && (size_t)ret < count)
+ btrfs_delalloc_release_space(inode, data_reserved,
+ offset, count - (size_t)ret);
++ btrfs_delalloc_release_extents(BTRFS_I(inode), count);
+ }
+ out:
+ if (wakeup)
+@@ -9274,6 +9275,7 @@ int btrfs_create_subvol_root(struct btrf
+
+ struct inode *btrfs_alloc_inode(struct super_block *sb)
+ {
++ struct btrfs_fs_info *fs_info = btrfs_sb(sb);
+ struct btrfs_inode *ei;
+ struct inode *inode;
+
+@@ -9299,8 +9301,9 @@ struct inode *btrfs_alloc_inode(struct s
+
+ spin_lock_init(&ei->lock);
+ ei->outstanding_extents = 0;
+- ei->reserved_extents = 0;
+-
++ if (sb->s_magic != BTRFS_TEST_MAGIC)
++ btrfs_init_metadata_block_rsv(fs_info, &ei->block_rsv,
++ BTRFS_BLOCK_RSV_DELALLOC);
+ ei->runtime_flags = 0;
+ ei->force_compress = BTRFS_COMPRESS_NONE;
+
+@@ -9348,8 +9351,9 @@ void btrfs_destroy_inode(struct inode *i
+
+ WARN_ON(!hlist_empty(&inode->i_dentry));
+ WARN_ON(inode->i_data.nrpages);
++ WARN_ON(BTRFS_I(inode)->block_rsv.reserved);
++ WARN_ON(BTRFS_I(inode)->block_rsv.size);
+ WARN_ON(BTRFS_I(inode)->outstanding_extents);
+- WARN_ON(BTRFS_I(inode)->reserved_extents);
+ WARN_ON(BTRFS_I(inode)->delalloc_bytes);
+ WARN_ON(BTRFS_I(inode)->csum_bytes);
+ WARN_ON(BTRFS_I(inode)->defrag_bytes);
diff --git a/patches.suse/0020-btrfs-remove-type-argument-from-comp_tree_refs.patch b/patches.suse/0020-btrfs-remove-type-argument-from-comp_tree_refs.patch
new file mode 100644
index 0000000000..b8cf1aaa26
--- /dev/null
+++ b/patches.suse/0020-btrfs-remove-type-argument-from-comp_tree_refs.patch
@@ -0,0 +1,57 @@
+From 3b60d436a165f890597d0226def17858973fa985 Mon Sep 17 00:00:00 2001
+From: Josef Bacik <josef@toxicpanda.com>
+Date: Fri, 29 Sep 2017 15:43:58 -0400
+Patch-mainline: v4.15
+Git-commit: 3b60d436a165f890597d0226def17858973fa985
+References: dependency for bsc#1031392
+Subject: [PATCH] btrfs: remove type argument from comp_tree_refs
+
+We can get this from the ref we've passed in.
+
+Signed-off-by: Josef Bacik <jbacik@fb.com>
+Reviewed-by: David Sterba <dsterba@suse.com>
+Signed-off-by: David Sterba <dsterba@suse.com>
+Signed-off-by: Qu Wenruo <wqu@suse.com>
+---
+ fs/btrfs/delayed-ref.c | 10 ++++------
+ 1 file changed, 4 insertions(+), 6 deletions(-)
+
+diff --git a/fs/btrfs/delayed-ref.c b/fs/btrfs/delayed-ref.c
+index b9b41c838da4..a2973340a94f 100644
+--- a/fs/btrfs/delayed-ref.c
++++ b/fs/btrfs/delayed-ref.c
+@@ -41,9 +41,9 @@ struct kmem_cache *btrfs_delayed_extent_op_cachep;
+ * compare two delayed tree backrefs with same bytenr and type
+ */
+ static int comp_tree_refs(struct btrfs_delayed_tree_ref *ref2,
+- struct btrfs_delayed_tree_ref *ref1, int type)
++ struct btrfs_delayed_tree_ref *ref1)
+ {
+- if (type == BTRFS_TREE_BLOCK_REF_KEY) {
++ if (ref1->node.type == BTRFS_TREE_BLOCK_REF_KEY) {
+ if (ref1->root < ref2->root)
+ return -1;
+ if (ref1->root > ref2->root)
+@@ -223,8 +223,7 @@ static bool merge_ref(struct btrfs_trans_handle *trans,
+ if ((ref->type == BTRFS_TREE_BLOCK_REF_KEY ||
+ ref->type == BTRFS_SHARED_BLOCK_REF_KEY) &&
+ comp_tree_refs(btrfs_delayed_node_to_tree_ref(ref),
+- btrfs_delayed_node_to_tree_ref(next),
+- ref->type))
++ btrfs_delayed_node_to_tree_ref(next)))
+ goto next;
+ if ((ref->type == BTRFS_EXTENT_DATA_REF_KEY ||
+ ref->type == BTRFS_SHARED_DATA_REF_KEY) &&
+@@ -409,8 +408,7 @@ add_delayed_ref_tail_merge(struct btrfs_trans_handle *trans,
+ if ((exist->type == BTRFS_TREE_BLOCK_REF_KEY ||
+ exist->type == BTRFS_SHARED_BLOCK_REF_KEY) &&
+ comp_tree_refs(btrfs_delayed_node_to_tree_ref(exist),
+- btrfs_delayed_node_to_tree_ref(ref),
+- ref->type))
++ btrfs_delayed_node_to_tree_ref(ref)))
+ goto add_tail;
+ if ((exist->type == BTRFS_EXTENT_DATA_REF_KEY ||
+ exist->type == BTRFS_SHARED_DATA_REF_KEY) &&
+--
+2.19.0
+
diff --git a/patches.suse/0021-btrfs-switch-args-for-comp_-_refs.patch b/patches.suse/0021-btrfs-switch-args-for-comp_-_refs.patch
new file mode 100644
index 0000000000..290137fb3b
--- /dev/null
+++ b/patches.suse/0021-btrfs-switch-args-for-comp_-_refs.patch
@@ -0,0 +1,49 @@
+From c7ad7c843965d8691269f581e132633a4ca9ef91 Mon Sep 17 00:00:00 2001
+From: Josef Bacik <josef@toxicpanda.com>
+Date: Thu, 19 Oct 2017 14:15:58 -0400
+Patch-mainline: v4.15
+Git-commit: c7ad7c843965d8691269f581e132633a4ca9ef91
+References: dependency for bsc#1031392
+Subject: [PATCH 21/25] btrfs: switch args for comp_*_refs
+
+Make it more consistent, we want the inserted ref to be compared against
+what's already in there. This will make the order go from lowest seq ->
+highest seq, which will make us more likely to make forward progress if
+there's a seqlock currently held.
+
+Signed-off-by: Josef Bacik <jbacik@fb.com>
+Signed-off-by: David Sterba <dsterba@suse.com>
+Signed-off-by: Qu Wenruo <wqu@suse.com>
+---
+ fs/btrfs/delayed-ref.c | 8 ++++----
+ 1 file changed, 4 insertions(+), 4 deletions(-)
+
+diff --git a/fs/btrfs/delayed-ref.c b/fs/btrfs/delayed-ref.c
+index a2973340a94f..bc940bb374cf 100644
+--- a/fs/btrfs/delayed-ref.c
++++ b/fs/btrfs/delayed-ref.c
+@@ -40,8 +40,8 @@ struct kmem_cache *btrfs_delayed_extent_op_cachep;
+ /*
+ * compare two delayed tree backrefs with same bytenr and type
+ */
+-static int comp_tree_refs(struct btrfs_delayed_tree_ref *ref2,
+- struct btrfs_delayed_tree_ref *ref1)
++static int comp_tree_refs(struct btrfs_delayed_tree_ref *ref1,
++ struct btrfs_delayed_tree_ref *ref2)
+ {
+ if (ref1->node.type == BTRFS_TREE_BLOCK_REF_KEY) {
+ if (ref1->root < ref2->root)
+@@ -60,8 +60,8 @@ static int comp_tree_refs(struct btrfs_delayed_tree_ref *ref2,
+ /*
+ * compare two delayed data backrefs with same bytenr and type
+ */
+-static int comp_data_refs(struct btrfs_delayed_data_ref *ref2,
+- struct btrfs_delayed_data_ref *ref1)
++static int comp_data_refs(struct btrfs_delayed_data_ref *ref1,
++ struct btrfs_delayed_data_ref *ref2)
+ {
+ if (ref1->node.type == BTRFS_EXTENT_DATA_REF_KEY) {
+ if (ref1->root < ref2->root)
+--
+2.19.0
+
diff --git a/patches.suse/0022-btrfs-add-a-comp_refs-helper.patch b/patches.suse/0022-btrfs-add-a-comp_refs-helper.patch
new file mode 100644
index 0000000000..f1b51ec690
--- /dev/null
+++ b/patches.suse/0022-btrfs-add-a-comp_refs-helper.patch
@@ -0,0 +1,101 @@
+From 1d148e5939f55c76d06108548c7c0226e55dde8e Mon Sep 17 00:00:00 2001
+From: Josef Bacik <josef@toxicpanda.com>
+Date: Thu, 19 Oct 2017 14:15:59 -0400
+Patch-mainline: v4.15
+Git-commit: c7ad7c843965d8691269f581e132633a4ca9ef91
+References: dependency for bsc#1031392
+Subject: [PATCH 22/25] btrfs: add a comp_refs() helper
+
+Instead of open-coding the delayed ref comparisons, add a helper to do
+the comparisons generically and use that everywhere. We compare
+sequence numbers last for following patches.
+
+Signed-off-by: Josef Bacik <jbacik@fb.com>
+Signed-off-by: David Sterba <dsterba@suse.com>
+Signed-off-by: Qu Wenruo <wqu@suse.com>
+---
+ fs/btrfs/delayed-ref.c | 54 +++++++++++++++++++++++-------------------
+ 1 file changed, 30 insertions(+), 24 deletions(-)
+
+diff --git a/fs/btrfs/delayed-ref.c b/fs/btrfs/delayed-ref.c
+index bc940bb374cf..8c7d7db01f7a 100644
+--- a/fs/btrfs/delayed-ref.c
++++ b/fs/btrfs/delayed-ref.c
+@@ -85,6 +85,34 @@ static int comp_data_refs(struct btrfs_delayed_data_ref *ref1,
+ return 0;
+ }
+
++static int comp_refs(struct btrfs_delayed_ref_node *ref1,
++ struct btrfs_delayed_ref_node *ref2,
++ bool check_seq)
++{
++ int ret = 0;
++
++ if (ref1->type < ref2->type)
++ return -1;
++ if (ref1->type > ref2->type)
++ return 1;
++ if (ref1->type == BTRFS_TREE_BLOCK_REF_KEY ||
++ ref1->type == BTRFS_SHARED_BLOCK_REF_KEY)
++ ret = comp_tree_refs(btrfs_delayed_node_to_tree_ref(ref1),
++ btrfs_delayed_node_to_tree_ref(ref2));
++ else
++ ret = comp_data_refs(btrfs_delayed_node_to_data_ref(ref1),
++ btrfs_delayed_node_to_data_ref(ref2));
++ if (ret)
++ return ret;
++ if (check_seq) {
++ if (ref1->seq < ref2->seq)
++ return -1;
++ if (ref1->seq > ref2->seq)
++ return 1;
++ }
++ return 0;
++}
++
+ /* insert a new ref to head ref rbtree */
+ static struct btrfs_delayed_ref_head *htree_insert(struct rb_root *root,
+ struct rb_node *node)
+@@ -217,18 +245,7 @@ static bool merge_ref(struct btrfs_trans_handle *trans,
+ if (seq && next->seq >= seq)
+ goto next;
+
+- if (next->type != ref->type)
+- goto next;
+-
+- if ((ref->type == BTRFS_TREE_BLOCK_REF_KEY ||
+- ref->type == BTRFS_SHARED_BLOCK_REF_KEY) &&
+- comp_tree_refs(btrfs_delayed_node_to_tree_ref(ref),
+- btrfs_delayed_node_to_tree_ref(next)))
+- goto next;
+- if ((ref->type == BTRFS_EXTENT_DATA_REF_KEY ||
+- ref->type == BTRFS_SHARED_DATA_REF_KEY) &&
+- comp_data_refs(btrfs_delayed_node_to_data_ref(ref),
+- btrfs_delayed_node_to_data_ref(next)))
++ if (comp_refs(ref, next, false))
+ goto next;
+
+ if (ref->action == next->action) {
+@@ -402,18 +419,7 @@ add_delayed_ref_tail_merge(struct btrfs_trans_handle *trans,
+ exist = list_entry(href->ref_list.prev, struct btrfs_delayed_ref_node,
+ list);
+ /* No need to compare bytenr nor is_head */
+- if (exist->type != ref->type || exist->seq != ref->seq)
+- goto add_tail;
+-
+- if ((exist->type == BTRFS_TREE_BLOCK_REF_KEY ||
+- exist->type == BTRFS_SHARED_BLOCK_REF_KEY) &&
+- comp_tree_refs(btrfs_delayed_node_to_tree_ref(exist),
+- btrfs_delayed_node_to_tree_ref(ref)))
+- goto add_tail;
+- if ((exist->type == BTRFS_EXTENT_DATA_REF_KEY ||
+- exist->type == BTRFS_SHARED_DATA_REF_KEY) &&
+- comp_data_refs(btrfs_delayed_node_to_data_ref(exist),
+- btrfs_delayed_node_to_data_ref(ref)))
++ if (comp_refs(exist, ref, true))
+ goto add_tail;
+
+ /* Now we are sure we can merge */
+--
+2.19.0
+
diff --git a/patches.suse/0023-btrfs-qgroup-Use-separate-meta-reservation-type-for-.patch b/patches.suse/0023-btrfs-qgroup-Use-separate-meta-reservation-type-for-.patch
new file mode 100644
index 0000000000..f2c98cec55
--- /dev/null
+++ b/patches.suse/0023-btrfs-qgroup-Use-separate-meta-reservation-type-for-.patch
@@ -0,0 +1,478 @@
+From 43b18595d6603cb4197fb9b063915cd7802141a6 Mon Sep 17 00:00:00 2001
+From: Qu Wenruo <wqu@suse.com>
+Date: Tue, 12 Dec 2017 15:34:32 +0800
+Patch-mainline: v4.17-rc1
+Git-commit: 43b18595d6603cb4197fb9b063915cd7802141a6
+References: bsc#1031392
+Subject: [PATCH] btrfs: qgroup: Use separate meta reservation type for
+ delalloc
+
+Before this patch, btrfs qgroup is mixing per-transcation meta rsv with
+preallocated meta rsv, making it quite easy to underflow qgroup meta
+reservation.
+
+Since we have the new qgroup meta rsv types, apply it to delalloc
+reservation.
+
+Now for delalloc, most of its reserved space will use META_PREALLOC qgroup
+rsv type.
+
+And for callers reducing outstanding extent like btrfs_finish_ordered_io(),
+they will convert corresponding META_PREALLOC reservation to
+META_PERTRANS.
+
+This is mainly due to the fact that current qgroup numbers will only be
+updated in btrfs_commit_transaction(), that's to say if we don't keep
+such placeholder reservation, we can exceed qgroup limitation.
+
+And for callers freeing outstanding extent in error handler, we will
+just free META_PREALLOC bytes.
+
+This behavior makes callers of btrfs_qgroup_release_meta() or
+btrfs_qgroup_convert_meta() to be aware of which type they are.
+So in this patch, btrfs_delalloc_release_metadata() and its callers get
+an extra parameter to info qgroup to do correct meta convert/release.
+
+The good news is, even we use the wrong type (convert or free), it won't
+cause obvious bug, as prealloc type is always in good shape, and the
+type only affects how per-trans meta is increased or not.
+
+So the worst case will be at most metadata limitation can be sometimes
+exceeded (no convert at all) or metadata limitation is reached too soon
+(no free at all).
+
+Signed-off-by: Qu Wenruo <wqu@suse.com>
+Signed-off-by: David Sterba <dsterba@suse.com>
+---
+ fs/btrfs/ctree.h | 10 ++++++----
+ fs/btrfs/extent-tree.c | 43 ++++++++++++++++++++++++-------------------
+ fs/btrfs/file.c | 16 +++++++++-------
+ fs/btrfs/free-space-cache.c | 3 ++-
+ fs/btrfs/inode-map.c | 4 ++--
+ fs/btrfs/inode.c | 27 ++++++++++++++-------------
+ fs/btrfs/ioctl.c | 10 ++++++----
+ fs/btrfs/ordered-data.c | 2 +-
+ fs/btrfs/relocation.c | 9 +++++----
+ 9 files changed, 69 insertions(+), 55 deletions(-)
+
+--- a/fs/btrfs/ctree.h
++++ b/fs/btrfs/ctree.h
+@@ -2682,7 +2682,8 @@ int btrfs_alloc_data_chunk_ondemand(stru
+ void btrfs_free_reserved_data_space(struct inode *inode,
+ struct extent_changeset *reserved, u64 start, u64 len);
+ void btrfs_delalloc_release_space(struct inode *inode,
+- struct extent_changeset *reserved, u64 start, u64 len);
++ struct extent_changeset *reserved,
++ u64 start, u64 len, bool qgroup_free);
+ void btrfs_free_reserved_data_space_noquota(struct inode *inode, u64 start,
+ u64 len);
+ void btrfs_trans_release_metadata(struct btrfs_trans_handle *trans,
+@@ -2698,10 +2699,11 @@ int btrfs_subvolume_reserve_metadata(str
+ void btrfs_subvolume_release_metadata(struct btrfs_root *root,
+ struct btrfs_block_rsv *rsv,
+ u64 qgroup_reserved);
+-void btrfs_delalloc_release_extents(struct btrfs_inode *inode, u64 num_bytes);
+-
++void btrfs_delalloc_release_extents(struct btrfs_inode *inode, u64 num_bytes,
++ bool qgroup_free);
+ int btrfs_delalloc_reserve_metadata(struct inode *inode, u64 num_bytes);
+-void btrfs_delalloc_release_metadata(struct inode *inode, u64 num_bytes);
++void btrfs_delalloc_release_metadata(struct inode *inode, u64 num_bytes,
++ bool qgroup_free);
+ int btrfs_delalloc_reserve_space(struct inode *inode,
+ struct extent_changeset **reserved, u64 start, u64 len);
+ void btrfs_init_block_rsv(struct btrfs_block_rsv *rsv, unsigned short type);
+--- a/fs/btrfs/extent-tree.c
++++ b/fs/btrfs/extent-tree.c
+@@ -5703,6 +5703,9 @@ int btrfs_inode_rsv_refill(struct btrfs_
+ if (num_bytes == 0)
+ return 0;
+
++ ret = btrfs_qgroup_reserve_meta_prealloc(root, num_bytes, true);
++ if (ret)
++ return ret;
+ ret = reserve_metadata_bytes(root, block_rsv, num_bytes, flush);
+ if (!ret) {
+ block_rsv_add_bytes(block_rsv, num_bytes, 0);
+@@ -5716,11 +5719,15 @@ int btrfs_inode_rsv_refill(struct btrfs_
+ /**
+ * btrfs_inode_rsv_release - release any excessive reservation.
+ * @inode - the inode we need to release from.
++ * @qgroup_free - free or convert qgroup meta.
++ * Unlike normal operation, qgroup meta reservation needs to know if we are
++ * freeing qgroup reservation or just converting it into per-trans. Normally
++ * @qgroup_free is true for error handling, and false for normal release.
+ *
+ * This is the same as btrfs_block_rsv_release, except that it handles the
+ * tracepoint for the reservation.
+ */
+-void btrfs_inode_rsv_release(struct btrfs_inode *inode)
++void btrfs_inode_rsv_release(struct btrfs_inode *inode, bool qgroup_free)
+ {
+ struct btrfs_fs_info *fs_info = inode->root->fs_info;
+ struct btrfs_block_rsv *global_rsv = &fs_info->global_block_rsv;
+@@ -5737,6 +5744,10 @@ void btrfs_inode_rsv_release(struct btrf
+ trace_btrfs_space_reservation(fs_info, "delalloc",
+ btrfs_ino(&inode->vfs_inode),
+ released, 0);
++ if (qgroup_free)
++ btrfs_qgroup_free_meta_prealloc(inode->root, released);
++ else
++ btrfs_qgroup_convert_reserved_meta(inode->root, released);
+ }
+
+ void btrfs_block_rsv_release(struct btrfs_root *root,
+@@ -6028,19 +6039,9 @@ int btrfs_delalloc_reserve_metadata(stru
+ btrfs_calculate_inode_block_rsv_size(root->fs_info, BTRFS_I(inode));
+ spin_unlock(&BTRFS_I(inode)->lock);
+
+- if (test_bit(BTRFS_FS_QUOTA_ENABLED, &root->fs_info->flags)) {
+- ret = btrfs_qgroup_reserve_meta_prealloc(root,
+- nr_extents * root->nodesize, true);
+- if (ret)
+- goto out_fail;
+- }
+-
+ ret = btrfs_inode_rsv_refill(BTRFS_I(inode), flush);
+- if (unlikely(ret)) {
+- btrfs_qgroup_free_meta_prealloc(root,
+- nr_extents * root->nodesize);
++ if (unlikely(ret))
+ goto out_fail;
+- }
+
+ if (delalloc_lock)
+ mutex_unlock(&BTRFS_I(inode)->delalloc_mutex);
+@@ -6054,7 +6055,7 @@ out_fail:
+ BTRFS_I(inode)->csum_bytes -= num_bytes;
+ btrfs_calculate_inode_block_rsv_size(root->fs_info, BTRFS_I(inode));
+ spin_unlock(&BTRFS_I(inode)->lock);
+- btrfs_inode_rsv_release(BTRFS_I(inode));
++ btrfs_inode_rsv_release(BTRFS_I(inode), true);
+ if (delalloc_lock)
+ mutex_unlock(&BTRFS_I(inode)->delalloc_mutex);
+ return ret;
+@@ -6064,12 +6065,14 @@ out_fail:
+ * btrfs_delalloc_release_metadata - release a metadata reservation for an inode
+ * @inode: the inode to release the reservation for.
+ * @num_bytes: the number of bytes we are releasing.
++ * @qgroup_free: free qgroup reservation or convert it to per-trans reservation
+ *
+ * This will release the metadata reservation for an inode. This can be called
+ * once we complete IO for a given set of bytes to release their metadata
+ * reservations, or on error for the same reason.
+ */
+-void btrfs_delalloc_release_metadata(struct inode *inode, u64 num_bytes)
++void btrfs_delalloc_release_metadata(struct inode *inode, u64 num_bytes,
++ bool qgroup_free)
+ {
+ struct btrfs_root *root = BTRFS_I(inode)->root;
+
+@@ -6081,13 +6084,14 @@ void btrfs_delalloc_release_metadata(str
+
+ if (btrfs_test_is_dummy_root(root))
+ return;
+- btrfs_inode_rsv_release(BTRFS_I(inode));
++ btrfs_inode_rsv_release(BTRFS_I(inode), qgroup_free);
+ }
+
+ /**
+ * btrfs_delalloc_release_extents - release our outstanding_extents
+ * @inode: the inode to balance the reservation for.
+ * @num_bytes: the number of bytes we originally reserved with
++ * @qgroup_free: do we need to free qgroup meta reservation or convert them.
+ *
+ * When we reserve space we increase outstanding_extents for the extents we may
+ * add. Once we've set the range as delalloc or created our ordered extents we
+@@ -6095,7 +6099,8 @@ void btrfs_delalloc_release_metadata(str
+ * temporarily tracked outstanding_extents. This _must_ be used in conjunction
+ * with btrfs_delalloc_reserve_metadata.
+ */
+-void btrfs_delalloc_release_extents(struct btrfs_inode *inode, u64 num_bytes)
++void btrfs_delalloc_release_extents(struct btrfs_inode *inode, u64 num_bytes,
++ bool qgroup_free)
+ {
+ struct btrfs_fs_info *fs_info = btrfs_sb(inode->vfs_inode.i_sb);
+ unsigned num_extents;
+@@ -6108,7 +6113,7 @@ void btrfs_delalloc_release_extents(stru
+
+ if (btrfs_is_testing(fs_info))
+ return;
+- btrfs_inode_rsv_release(inode);
++ btrfs_inode_rsv_release(inode, qgroup_free);
+ }
+
+ /**
+@@ -6166,9 +6171,9 @@ int btrfs_delalloc_reserve_space(struct
+ */
+ void btrfs_delalloc_release_space(struct inode *inode,
+ struct extent_changeset *reserved,
+- u64 start, u64 len)
++ u64 start, u64 len, bool qgroup_free)
+ {
+- btrfs_delalloc_release_metadata(inode, len);
++ btrfs_delalloc_release_metadata(inode, len, qgroup_free);
+ btrfs_free_reserved_data_space(inode, reserved, start, len);
+ }
+
+--- a/fs/btrfs/file.c
++++ b/fs/btrfs/file.c
+@@ -1610,7 +1610,7 @@ again:
+ force_page_uptodate);
+ if (ret) {
+ btrfs_delalloc_release_extents(BTRFS_I(inode),
+- reserve_bytes);
++ reserve_bytes, true);
+ break;
+ }
+
+@@ -1622,7 +1622,7 @@ again:
+ if (extents_locked == -EAGAIN)
+ goto again;
+ btrfs_delalloc_release_extents(BTRFS_I(inode),
+- reserve_bytes);
++ reserve_bytes, true);
+ ret = extents_locked;
+ break;
+ }
+@@ -1662,7 +1662,7 @@ again:
+
+ if (only_release_metadata) {
+ btrfs_delalloc_release_metadata(inode,
+- release_bytes);
++ release_bytes, true);
+ } else {
+ u64 __pos;
+
+@@ -1670,7 +1670,7 @@ again:
+ (dirty_pages << PAGE_CACHE_SHIFT);
+ btrfs_delalloc_release_space(inode,
+ data_reserved, __pos,
+- release_bytes);
++ release_bytes, true);
+ }
+ }
+
+@@ -1685,7 +1685,8 @@ again:
+ unlock_extent_cached(&BTRFS_I(inode)->io_tree,
+ lockstart, lockend, &cached_state,
+ GFP_NOFS);
+- btrfs_delalloc_release_extents(BTRFS_I(inode), reserve_bytes);
++ btrfs_delalloc_release_extents(BTRFS_I(inode), reserve_bytes,
++ (ret != 0));
+ if (ret) {
+ btrfs_drop_pages(pages, num_pages);
+ break;
+@@ -1722,11 +1723,12 @@ again:
+ if (release_bytes) {
+ if (only_release_metadata) {
+ btrfs_end_write_no_snapshoting(root);
+- btrfs_delalloc_release_metadata(inode, release_bytes);
++ btrfs_delalloc_release_metadata(inode, release_bytes,
++ true);
+ } else {
+ btrfs_delalloc_release_space(inode, data_reserved,
+ round_down(pos, root->sectorsize),
+- release_bytes);
++ release_bytes, true);
+ }
+ }
+
+--- a/fs/btrfs/free-space-cache.c
++++ b/fs/btrfs/free-space-cache.c
+@@ -3545,7 +3545,8 @@ int btrfs_write_out_ino_cache(struct btr
+
+ if (ret) {
+ if (release_metadata)
+- btrfs_delalloc_release_metadata(inode, inode->i_size);
++ btrfs_delalloc_release_metadata(inode, inode->i_size,
++ true);
+ #ifdef DEBUG
+ btrfs_err(root->fs_info,
+ "failed to write free ino cache for root %llu",
+--- a/fs/btrfs/inode-map.c
++++ b/fs/btrfs/inode-map.c
+@@ -499,12 +499,12 @@ again:
+ ret = btrfs_prealloc_file_range_trans(inode, trans, 0, 0, prealloc,
+ prealloc, prealloc, &alloc_hint);
+ if (ret) {
+- btrfs_delalloc_release_extents(BTRFS_I(inode), prealloc);
++ btrfs_delalloc_release_extents(BTRFS_I(inode), prealloc, true);
+ goto out_put;
+ }
+
+ ret = btrfs_write_out_ino_cache(root, trans, path, inode);
+- btrfs_delalloc_release_extents(BTRFS_I(inode), prealloc);
++ btrfs_delalloc_release_extents(BTRFS_I(inode), prealloc, false);
+ out_put:
+ iput(inode);
+ out_release:
+--- a/fs/btrfs/inode.c
++++ b/fs/btrfs/inode.c
+@@ -1838,7 +1838,7 @@ static void btrfs_clear_bit_hook(struct
+ */
+ if (*bits & EXTENT_CLEAR_META_RESV &&
+ root != root->fs_info->tree_root)
+- btrfs_delalloc_release_metadata(inode, len);
++ btrfs_delalloc_release_metadata(inode, len, false);
+
+ /* For sanity tests. */
+ if (btrfs_test_is_dummy_root(root))
+@@ -2097,7 +2097,7 @@ again:
+
+ ClearPageChecked(page);
+ set_page_dirty(page);
+- btrfs_delalloc_release_extents(BTRFS_I(inode), PAGE_SIZE);
++ btrfs_delalloc_release_extents(BTRFS_I(inode), PAGE_SIZE, false);
+ out:
+ unlock_extent_cached(&BTRFS_I(inode)->io_tree, page_start, page_end,
+ &cached_state, GFP_NOFS);
+@@ -4778,8 +4778,8 @@ again:
+ page = find_or_create_page(mapping, index, mask);
+ if (!page) {
+ btrfs_delalloc_release_space(inode, data_reserved,
+- block_start, blocksize);
+- btrfs_delalloc_release_extents(BTRFS_I(inode), blocksize);
++ block_start, blocksize, true);
++ btrfs_delalloc_release_extents(BTRFS_I(inode), blocksize, true);
+ ret = -ENOMEM;
+ goto out;
+ }
+@@ -4847,8 +4847,8 @@ again:
+ out_unlock:
+ if (ret)
+ btrfs_delalloc_release_space(inode, data_reserved, block_start,
+- blocksize);
+- btrfs_delalloc_release_extents(BTRFS_I(inode), blocksize);
++ blocksize, true);
++ btrfs_delalloc_release_extents(BTRFS_I(inode), blocksize, (ret != 0));
+ unlock_page(page);
+ page_cache_release(page);
+ out:
+@@ -8698,7 +8698,7 @@ static ssize_t btrfs_direct_IO(struct ki
+ if (ret < 0 && ret != -EIOCBQUEUED) {
+ if (dio_data.reserve)
+ btrfs_delalloc_release_space(inode, data_reserved,
+- offset, dio_data.reserve);
++ offset, dio_data.reserve, true);
+ /*
+ * On error we might have left some ordered extents
+ * without submitting corresponding bios for them, so
+@@ -8714,8 +8714,8 @@ static ssize_t btrfs_direct_IO(struct ki
+ 0);
+ } else if (ret >= 0 && (size_t)ret < count)
+ btrfs_delalloc_release_space(inode, data_reserved,
+- offset, count - (size_t)ret);
+- btrfs_delalloc_release_extents(BTRFS_I(inode), count);
++ offset, count - (size_t)ret, true);
++ btrfs_delalloc_release_extents(BTRFS_I(inode), count, false);
+ }
+ out:
+ if (wakeup)
+@@ -9031,7 +9031,8 @@ again:
+ if (reserved_space < PAGE_CACHE_SIZE) {
+ end = page_start + reserved_space - 1;
+ btrfs_delalloc_release_space(inode, data_reserved,
+- page_start, PAGE_CACHE_SIZE - reserved_space);
++ page_start, PAGE_CACHE_SIZE - reserved_space,
++ true);
+ }
+ }
+
+@@ -9081,16 +9082,16 @@ again:
+
+ out_unlock:
+ if (!ret) {
+- btrfs_delalloc_release_extents(BTRFS_I(inode), PAGE_SIZE);
++ btrfs_delalloc_release_extents(BTRFS_I(inode), PAGE_SIZE, true);
+ sb_end_pagefault(inode->i_sb);
+ extent_changeset_free(data_reserved);
+ return VM_FAULT_LOCKED;
+ }
+ unlock_page(page);
+ out:
+- btrfs_delalloc_release_extents(BTRFS_I(inode), PAGE_SIZE);
++ btrfs_delalloc_release_extents(BTRFS_I(inode), PAGE_SIZE, (ret != 0));
+ btrfs_delalloc_release_space(inode, data_reserved, page_start,
+- reserved_space);
++ reserved_space, (ret != 0));
+ out_noreserve:
+ sb_end_pagefault(inode->i_sb);
+ extent_changeset_free(data_reserved);
+--- a/fs/btrfs/ioctl.c
++++ b/fs/btrfs/ioctl.c
+@@ -1232,7 +1232,7 @@ again:
+ spin_unlock(&BTRFS_I(inode)->lock);
+ btrfs_delalloc_release_space(inode, data_reserved,
+ start_index << PAGE_CACHE_SHIFT,
+- (page_cnt - i_done) << PAGE_CACHE_SHIFT);
++ (page_cnt - i_done) << PAGE_CACHE_SHIFT, true);
+ }
+
+
+@@ -1251,7 +1251,8 @@ again:
+ unlock_page(pages[i]);
+ page_cache_release(pages[i]);
+ }
+- btrfs_delalloc_release_extents(BTRFS_I(inode), page_cnt << PAGE_SHIFT);
++ btrfs_delalloc_release_extents(BTRFS_I(inode), page_cnt << PAGE_SHIFT,
++ false);
+ extent_changeset_free(data_reserved);
+ return i_done;
+ out:
+@@ -1261,8 +1262,9 @@ out:
+ }
+ btrfs_delalloc_release_space(inode, data_reserved,
+ start_index << PAGE_CACHE_SHIFT,
+- page_cnt << PAGE_CACHE_SHIFT);
+- btrfs_delalloc_release_extents(BTRFS_I(inode), page_cnt << PAGE_SHIFT);
++ page_cnt << PAGE_CACHE_SHIFT, true);
++ btrfs_delalloc_release_extents(BTRFS_I(inode), page_cnt << PAGE_SHIFT,
++ true);
+ extent_changeset_free(data_reserved);
+ return ret;
+
+--- a/fs/btrfs/ordered-data.c
++++ b/fs/btrfs/ordered-data.c
+@@ -607,7 +607,7 @@ void btrfs_remove_ordered_extent(struct
+ btrfs_mod_outstanding_extents(btrfs_inode, -1);
+ spin_unlock(&btrfs_inode->lock);
+ if (root != root->fs_info->tree_root)
+- btrfs_delalloc_release_metadata(inode, entry->len);
++ btrfs_delalloc_release_metadata(inode, entry->len, false);
+
+ tree = &btrfs_inode->ordered_tree;
+ spin_lock_irq(&tree->lock);
+--- a/fs/btrfs/relocation.c
++++ b/fs/btrfs/relocation.c
+@@ -3231,7 +3231,7 @@ static int relocate_file_extent_cluster(
+ mask);
+ if (!page) {
+ btrfs_delalloc_release_metadata(inode,
+- PAGE_CACHE_SIZE);
++ PAGE_CACHE_SIZE, true);
+ ret = -ENOMEM;
+ goto out;
+ }
+@@ -3250,9 +3250,9 @@ static int relocate_file_extent_cluster(
+ unlock_page(page);
+ page_cache_release(page);
+ btrfs_delalloc_release_metadata(inode,
+- PAGE_CACHE_SIZE);
++ PAGE_CACHE_SIZE, true);
+ btrfs_delalloc_release_extents(BTRFS_I(inode),
+- PAGE_SIZE);
++ PAGE_SIZE, true);
+ ret = -EIO;
+ goto out;
+ }
+@@ -3282,7 +3282,8 @@ static int relocate_file_extent_cluster(
+ page_cache_release(page);
+
+ index++;
+- btrfs_delalloc_release_extents(BTRFS_I(inode), PAGE_SIZE);
++ btrfs_delalloc_release_extents(BTRFS_I(inode), PAGE_SIZE,
++ false);
+ balance_dirty_pages_ratelimited(inode->i_mapping);
+ btrfs_throttle(BTRFS_I(inode)->root);
+ }
diff --git a/patches.suse/0024-btrfs-Fix-wrong-btrfs_delalloc_release_extents-param.patch b/patches.suse/0024-btrfs-Fix-wrong-btrfs_delalloc_release_extents-param.patch
new file mode 100644
index 0000000000..7aa11a528e
--- /dev/null
+++ b/patches.suse/0024-btrfs-Fix-wrong-btrfs_delalloc_release_extents-param.patch
@@ -0,0 +1,35 @@
+From 336a8bb8e36a273a802a54b2e673c777c9c62fb1 Mon Sep 17 00:00:00 2001
+From: Qu Wenruo <wqu@suse.com>
+Date: Tue, 17 Apr 2018 18:43:58 +0800
+Patch-mainline: v4.17-rc2
+Git-commit: 336a8bb8e36a273a802a54b2e673c777c9c62fb1
+References: bsc#1031392
+Subject: [PATCH] btrfs: Fix wrong btrfs_delalloc_release_extents parameter
+
+Commit 43b18595d660 ("btrfs: qgroup: Use separate meta reservation type
+for delalloc") merged into mainline is not the latest version submitted
+to mail list in Dec 2017.
+
+It has a fatal wrong @qgroup_free parameter, which results increasing
+qgroup metadata pertrans reserved space, and causing a lot of early EDQUOT.
+
+Fix it by applying the correct diff on top of current branch.
+
+Fixes: 43b18595d660 ("btrfs: qgroup: Use separate meta reservation type for delalloc")
+Signed-off-by: Qu Wenruo <wqu@suse.com>
+Signed-off-by: David Sterba <dsterba@suse.com>
+---
+ fs/btrfs/file.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+--- a/fs/btrfs/file.c
++++ b/fs/btrfs/file.c
+@@ -1762,7 +1762,7 @@ again:
+ lockstart, lockend, &cached_state,
+ GFP_NOFS);
+ btrfs_delalloc_release_extents(BTRFS_I(inode), reserve_bytes,
+- (ret != 0));
++ true);
+ if (ret) {
+ btrfs_drop_pages(pages, num_pages);
+ break;
diff --git a/patches.suse/0025-btrfs-delayed-inode-Use-new-qgroup-meta-rsv-for-dela.patch b/patches.suse/0025-btrfs-delayed-inode-Use-new-qgroup-meta-rsv-for-dela.patch
new file mode 100644
index 0000000000..0628113609
--- /dev/null
+++ b/patches.suse/0025-btrfs-delayed-inode-Use-new-qgroup-meta-rsv-for-dela.patch
@@ -0,0 +1,100 @@
+From 4f5427ccce5d9cb8e2c8f98b49e744e523d246ec Mon Sep 17 00:00:00 2001
+From: Qu Wenruo <wqu@suse.com>
+Date: Tue, 12 Dec 2017 15:34:33 +0800
+Patch-mainline: v4.17-rc1
+Git-commit: 4f5427ccce5d9cb8e2c8f98b49e744e523d246ec
+References: bsc#1031392
+Subject: [PATCH 25/28] btrfs: delayed-inode: Use new qgroup meta rsv for
+ delayed inode and item
+
+Quite similar for delalloc, some modification to delayed-inode and
+delayed-item reservation. Also needs extra parameter for release case
+to distinguish normal release and error release.
+
+Signed-off-by: Qu Wenruo <wqu@suse.com>
+Signed-off-by: David Sterba <dsterba@suse.com>
+---
+ fs/btrfs/delayed-inode.c | 22 ++++++++++++++++++----
+ 1 file changed, 18 insertions(+), 4 deletions(-)
+
+--- a/fs/btrfs/delayed-inode.c
++++ b/fs/btrfs/delayed-inode.c
+@@ -22,6 +22,7 @@
+ #include "disk-io.h"
+ #include "transaction.h"
+ #include "ctree.h"
++#include "qgroup.h"
+
+ #define BTRFS_DELAYED_WRITEBACK 512
+ #define BTRFS_DELAYED_BACKGROUND 128
+@@ -579,6 +580,7 @@ static void btrfs_delayed_item_release_m
+ return;
+
+ rsv = &root->fs_info->delayed_block_rsv;
++ btrfs_qgroup_convert_reserved_meta(root, item->bytes_reserved);
+ trace_btrfs_space_reservation(root->fs_info, "delayed_item",
+ item->key.objectid, item->bytes_reserved,
+ 0);
+@@ -602,6 +604,9 @@ static int btrfs_delayed_inode_reserve_m
+
+ num_bytes = btrfs_calc_trans_metadata_size(root, 1);
+
++ ret = btrfs_qgroup_reserve_meta_prealloc(root, num_bytes, true);
++ if (ret < 0)
++ return ret;
+ /*
+ * btrfs_dirty_inode will update the inode under btrfs_join_transaction
+ * which doesn't reserve space for speed. This is a problem since we
+@@ -621,8 +626,10 @@ static int btrfs_delayed_inode_reserve_m
+ * EAGAIN to make us stop the transaction we have, so return
+ * ENOSPC instead so that btrfs_dirty_inode knows what to do.
+ */
+- if (ret == -EAGAIN)
++ if (ret == -EAGAIN) {
+ ret = -ENOSPC;
++ btrfs_qgroup_free_meta_prealloc(root, num_bytes);
++ }
+ if (!ret) {
+ node->bytes_reserved = num_bytes;
+ trace_btrfs_space_reservation(root->fs_info,
+@@ -645,7 +652,8 @@ static int btrfs_delayed_inode_reserve_m
+ }
+
+ static void btrfs_delayed_inode_release_metadata(struct btrfs_root *root,
+- struct btrfs_delayed_node *node)
++ struct btrfs_delayed_node *node,
++ bool qgroup_free)
+ {
+ struct btrfs_block_rsv *rsv;
+
+@@ -657,6 +665,12 @@ static void btrfs_delayed_inode_release_
+ node->inode_id, node->bytes_reserved, 0);
+ btrfs_block_rsv_release(root, rsv,
+ node->bytes_reserved);
++ if (qgroup_free)
++ btrfs_qgroup_free_meta_prealloc(node->root,
++ node->bytes_reserved);
++ else
++ btrfs_qgroup_convert_reserved_meta(node->root,
++ node->bytes_reserved);
+ node->bytes_reserved = 0;
+ }
+
+@@ -1039,7 +1053,7 @@ out:
+ no_iref:
+ btrfs_release_path(path);
+ err_out:
+- btrfs_delayed_inode_release_metadata(root, node);
++ btrfs_delayed_inode_release_metadata(root, node, (ret < 0));
+ btrfs_release_delayed_inode(node);
+
+ return ret;
+@@ -1879,7 +1893,7 @@ static void __btrfs_kill_delayed_node(st
+ btrfs_release_delayed_iref(delayed_node);
+
+ if (test_bit(BTRFS_DELAYED_NODE_INODE_DIRTY, &delayed_node->flags)) {
+- btrfs_delayed_inode_release_metadata(root, delayed_node);
++ btrfs_delayed_inode_release_metadata(root, delayed_node, false);
+ btrfs_release_delayed_inode(delayed_node);
+ }
+ mutex_unlock(&delayed_node->mutex);
diff --git a/patches.suse/0026-btrfs-qgroup-Use-root-qgroup_meta_rsv_-to-record-qgr.patch b/patches.suse/0026-btrfs-qgroup-Use-root-qgroup_meta_rsv_-to-record-qgr.patch
new file mode 100644
index 0000000000..bb043a4048
--- /dev/null
+++ b/patches.suse/0026-btrfs-qgroup-Use-root-qgroup_meta_rsv_-to-record-qgr.patch
@@ -0,0 +1,161 @@
+From 8287475a20552af66b32c07704dbdbeeb898ac1f Mon Sep 17 00:00:00 2001
+From: Qu Wenruo <wqu@suse.com>
+Date: Tue, 12 Dec 2017 15:34:34 +0800
+Patch-mainline: v4.17-rc1
+Git-commit: 8287475a20552af66b32c07704dbdbeeb898ac1f
+References: bsc#1031392
+Subject: [PATCH 26/28] btrfs: qgroup: Use root::qgroup_meta_rsv_* to record
+ qgroup meta reserved space
+
+For quota disabled->enable case, it's possible that at reservation time
+quota was not enabled so no bytes were really reserved, while at release
+time, quota was enabled so we will try to release some bytes we didn't
+really own.
+
+Such situation can cause metadata reserveation underflow, for both types,
+also less possible for per-trans type since quota enable will commit
+transaction.
+
+To address this, record qgroup meta reserved bytes into
+root::qgroup_meta_rsv_pertrans and ::prealloc.
+So at releasing time we won't free any bytes we didn't reserve.
+
+For DATA, it's already handled by io_tree, so nothing needs to be done
+there.
+
+Signed-off-by: Qu Wenruo <wqu@suse.com>
+Signed-off-by: David Sterba <dsterba@suse.com>
+---
+ fs/btrfs/ctree.h | 5 ++++
+ fs/btrfs/disk-io.c | 1
+ fs/btrfs/qgroup.c | 66 +++++++++++++++++++++++++++++++++++++++++++++++++----
+ 3 files changed, 68 insertions(+), 4 deletions(-)
+
+--- a/fs/btrfs/ctree.h
++++ b/fs/btrfs/ctree.h
+@@ -1230,6 +1230,11 @@ struct btrfs_root {
+ int send_in_progress;
+ struct btrfs_subvolume_writers *subv_writers;
+ atomic_t will_be_snapshoted;
++
++ /* For qgroup metadata reserved space */
++ spinlock_t qgroup_meta_rsv_lock;
++ u64 qgroup_meta_rsv_pertrans;
++ u64 qgroup_meta_rsv_prealloc;
+ };
+
+ static inline u32 __BTRFS_LEAF_DATA_SIZE(u32 blocksize)
+--- a/fs/btrfs/disk-io.c
++++ b/fs/btrfs/disk-io.c
+@@ -1271,6 +1271,7 @@ static void __setup_root(u32 nodesize, u
+ spin_lock_init(&root->accounting_lock);
+ spin_lock_init(&root->log_extents_lock[0]);
+ spin_lock_init(&root->log_extents_lock[1]);
++ spin_lock_init(&root->qgroup_meta_rsv_lock);
+ mutex_init(&root->objectid_mutex);
+ mutex_init(&root->log_mutex);
+ mutex_init(&root->ordered_extent_mutex);
+--- a/fs/btrfs/qgroup.c
++++ b/fs/btrfs/qgroup.c
+@@ -2520,11 +2520,11 @@ void btrfs_qgroup_free_refroot(struct bt
+ if (!qgroup)
+ goto out;
+
+- /*
+- * We're freeing all pertrans rsv, get current value from level 0
+- * qgroup as real num_bytes to free.
+- */
+ if (num_bytes == (u64)-1)
++ /*
++ * We're freeing all pertrans rsv, get reserved value from
++ * level 0 qgroup as real num_bytes to free.
++ */
+ num_bytes = qgroup->rsv.values[type];
+
+ ulist_reinit(fs_info->qgroup_ulist);
+@@ -3103,6 +3103,46 @@ int btrfs_qgroup_release_data(struct ino
+ return __btrfs_qgroup_release_data(inode, NULL, start, len, 0);
+ }
+
++static void add_root_meta_rsv(struct btrfs_root *root, int num_bytes,
++ enum btrfs_qgroup_rsv_type type)
++{
++ if (type != BTRFS_QGROUP_RSV_META_PREALLOC &&
++ type != BTRFS_QGROUP_RSV_META_PERTRANS)
++ return;
++ if (num_bytes == 0)
++ return;
++
++ spin_lock(&root->qgroup_meta_rsv_lock);
++ if (type == BTRFS_QGROUP_RSV_META_PREALLOC)
++ root->qgroup_meta_rsv_prealloc += num_bytes;
++ else
++ root->qgroup_meta_rsv_pertrans += num_bytes;
++ spin_unlock(&root->qgroup_meta_rsv_lock);
++}
++
++static int sub_root_meta_rsv(struct btrfs_root *root, int num_bytes,
++ enum btrfs_qgroup_rsv_type type)
++{
++ if (type != BTRFS_QGROUP_RSV_META_PREALLOC &&
++ type != BTRFS_QGROUP_RSV_META_PERTRANS)
++ return 0;
++ if (num_bytes == 0)
++ return 0;
++
++ spin_lock(&root->qgroup_meta_rsv_lock);
++ if (type == BTRFS_QGROUP_RSV_META_PREALLOC) {
++ num_bytes = min_t(u64, root->qgroup_meta_rsv_prealloc,
++ num_bytes);
++ root->qgroup_meta_rsv_prealloc -= num_bytes;
++ } else {
++ num_bytes = min_t(u64, root->qgroup_meta_rsv_pertrans,
++ num_bytes);
++ root->qgroup_meta_rsv_pertrans -= num_bytes;
++ }
++ spin_unlock(&root->qgroup_meta_rsv_lock);
++ return num_bytes;
++}
++
+ int __btrfs_qgroup_reserve_meta(struct btrfs_root *root, int num_bytes,
+ enum btrfs_qgroup_rsv_type type, bool enforce)
+ {
+@@ -3117,6 +3157,15 @@ int __btrfs_qgroup_reserve_meta(struct b
+ ret = qgroup_reserve(root, num_bytes, enforce, type);
+ if (ret < 0)
+ return ret;
++ /*
++ * Record what we have reserved into root.
++ *
++ * To avoid quota disabled->enabled underflow.
++ * In that case, we may try to free space we haven't reserved
++ * (since quota was disabled), so record what we reserved into root.
++ * And ensure later release won't underflow this number.
++ */
++ add_root_meta_rsv(root, num_bytes, type);
+ return ret;
+ }
+
+@@ -3142,6 +3191,12 @@ void __btrfs_qgroup_free_meta(struct btr
+ !is_fstree(root->objectid))
+ return;
+
++ /*
++ * reservation for META_PREALLOC can happen before quota is enabled,
++ * which can lead to underflow.
++ * Here ensure we will only free what we really have reserved.
++ */
++ num_bytes = sub_root_meta_rsv(root, num_bytes, type);
+ BUG_ON(num_bytes != round_down(num_bytes, root->nodesize));
+ trace_qgroup_meta_reserve(root, -(s64)num_bytes);
+ btrfs_qgroup_free_refroot(root->fs_info, root->objectid, num_bytes,
+@@ -3206,6 +3261,9 @@ void btrfs_qgroup_convert_reserved_meta(
+ if (!test_bit(BTRFS_FS_QUOTA_ENABLED, &fs_info->flags) ||
+ !is_fstree(root->objectid))
+ return;
++ /* Same as btrfs_qgroup_free_meta_prealloc() */
++ num_bytes = sub_root_meta_rsv(root, num_bytes,
++ BTRFS_QGROUP_RSV_META_PREALLOC);
+ qgroup_convert_meta(fs_info, root->objectid, num_bytes);
+ }
+
diff --git a/patches.suse/0027-btrfs-qgroup-Update-trace-events-for-metadata-reserv.patch b/patches.suse/0027-btrfs-qgroup-Update-trace-events-for-metadata-reserv.patch
new file mode 100644
index 0000000000..fdb313738d
--- /dev/null
+++ b/patches.suse/0027-btrfs-qgroup-Update-trace-events-for-metadata-reserv.patch
@@ -0,0 +1,141 @@
+From 4ee0d8832c2ecd08fd4ccbaa55484e6a500f2f34 Mon Sep 17 00:00:00 2001
+From: Qu Wenruo <wqu@suse.com>
+Date: Tue, 12 Dec 2017 15:34:35 +0800
+Patch-mainline: v4.17-rc1
+Git-commit: 4ee0d8832c2ecd08fd4ccbaa55484e6a500f2f34
+References: bsc#1031392
+Subject: [PATCH 27/28] btrfs: qgroup: Update trace events for metadata
+ reservation
+
+Now trace_qgroup_meta_reserve() will have extra type parameter.
+
+And introduce two new trace events:
+
+1) trace_qgroup_meta_free_all_pertrans()
+ For btrfs_qgroup_free_meta_all_pertrans()
+
+2) trace_qgroup_meta_convert()
+ For btrfs_qgroup_convert_reserved_meta()
+
+Signed-off-by: Qu Wenruo <wqu@suse.com>
+Signed-off-by: David Sterba <dsterba@suse.com>
+---
+ fs/btrfs/qgroup.c | 7 +++--
+ include/trace/events/btrfs.h | 55 +++++++++++++++++++++++++++++++++++++++++--
+ 2 files changed, 57 insertions(+), 5 deletions(-)
+
+--- a/fs/btrfs/qgroup.c
++++ b/fs/btrfs/qgroup.c
+@@ -3153,7 +3153,7 @@ int __btrfs_qgroup_reserve_meta(struct b
+ return 0;
+
+ BUG_ON(num_bytes != round_down(num_bytes, root->nodesize));
+- trace_qgroup_meta_reserve(root, (s64)num_bytes);
++ trace_qgroup_meta_reserve(root, type, (s64)num_bytes);
+ ret = qgroup_reserve(root, num_bytes, enforce, type);
+ if (ret < 0)
+ return ret;
+@@ -3178,7 +3178,7 @@ void btrfs_qgroup_free_meta_all_pertrans
+ return;
+
+ /* TODO: Update trace point to handle such free */
+- trace_qgroup_meta_reserve(root, 0);
++ trace_qgroup_meta_free_all_pertrans(root);
+ /* Special value -1 means to free all reserved space */
+ btrfs_qgroup_free_refroot(fs_info, root->objectid, (u64)-1,
+ BTRFS_QGROUP_RSV_META_PERTRANS);
+@@ -3198,7 +3198,7 @@ void __btrfs_qgroup_free_meta(struct btr
+ */
+ num_bytes = sub_root_meta_rsv(root, num_bytes, type);
+ BUG_ON(num_bytes != round_down(num_bytes, root->nodesize));
+- trace_qgroup_meta_reserve(root, -(s64)num_bytes);
++ trace_qgroup_meta_reserve(root, type, -(s64)num_bytes);
+ btrfs_qgroup_free_refroot(root->fs_info, root->objectid, num_bytes,
+ type);
+ }
+@@ -3264,6 +3264,7 @@ void btrfs_qgroup_convert_reserved_meta(
+ /* Same as btrfs_qgroup_free_meta_prealloc() */
+ num_bytes = sub_root_meta_rsv(root, num_bytes,
+ BTRFS_QGROUP_RSV_META_PREALLOC);
++ trace_qgroup_meta_convert(root, num_bytes);
+ qgroup_convert_meta(fs_info, root->objectid, num_bytes);
+ }
+
+--- a/include/trace/events/btrfs.h
++++ b/include/trace/events/btrfs.h
+@@ -1577,6 +1577,28 @@ TRACE_EVENT(qgroup_update_reserve,
+
+ TRACE_EVENT(qgroup_meta_reserve,
+
++ TP_PROTO(struct btrfs_root *root, s64 diff, int type),
++
++ TP_ARGS(root, diff, type),
++
++ TP_STRUCT__entry_btrfs(
++ __field( u64, refroot )
++ __field( s64, diff )
++ __field( int, type )
++ ),
++
++ TP_fast_assign_btrfs(root->fs_info,
++ __entry->refroot = root->objectid;
++ __entry->diff = diff;
++ ),
++
++ TP_printk_btrfs("refroot=%llu(%s) type=%s diff=%lld",
++ show_root_type(__entry->refroot),
++ show_qgroup_rsv_type(__entry->type), __entry->diff)
++);
++
++TRACE_EVENT(qgroup_meta_convert,
++
+ TP_PROTO(struct btrfs_root *root, s64 diff),
+
+ TP_ARGS(root, diff),
+@@ -1584,6 +1606,7 @@ TRACE_EVENT(qgroup_meta_reserve,
+ TP_STRUCT__entry_btrfs(
+ __field( u64, refroot )
+ __field( s64, diff )
++ __field( int, type )
+ ),
+
+ TP_fast_assign_btrfs(root->fs_info,
+@@ -1591,8 +1614,36 @@ TRACE_EVENT(qgroup_meta_reserve,
+ __entry->diff = diff;
+ ),
+
+- TP_printk_btrfs("refroot=%llu(%s) diff=%lld",
+- show_root_type(__entry->refroot), __entry->diff)
++ TP_printk_btrfs("refroot=%llu(%s) type=%s->%s diff=%lld",
++ show_root_type(__entry->refroot),
++ show_qgroup_rsv_type(BTRFS_QGROUP_RSV_META_PREALLOC),
++ show_qgroup_rsv_type(BTRFS_QGROUP_RSV_META_PERTRANS),
++ __entry->diff)
++);
++
++TRACE_EVENT(qgroup_meta_free_all_pertrans,
++
++ TP_PROTO(struct btrfs_root *root),
++
++ TP_ARGS(root),
++
++ TP_STRUCT__entry_btrfs(
++ __field( u64, refroot )
++ __field( s64, diff )
++ __field( int, type )
++ ),
++
++ TP_fast_assign_btrfs(root->fs_info,
++ __entry->refroot = root->objectid;
++ spin_lock(&root->qgroup_meta_rsv_lock);
++ __entry->diff = -(s64)root->qgroup_meta_rsv_pertrans;
++ spin_unlock(&root->qgroup_meta_rsv_lock);
++ __entry->type = BTRFS_QGROUP_RSV_META_PERTRANS;
++ ),
++
++ TP_printk_btrfs("refroot=%llu(%s) type=%s diff=%lld",
++ show_root_type(__entry->refroot),
++ show_qgroup_rsv_type(__entry->type), __entry->diff)
+ );
+
+ TRACE_EVENT(btrfs_inode_mod_outstanding_extents,
diff --git a/patches.suse/0028-Revert-btrfs-qgroups-Retry-after-commit-on-getting-E.patch b/patches.suse/0028-Revert-btrfs-qgroups-Retry-after-commit-on-getting-E.patch
new file mode 100644
index 0000000000..95d0e35319
--- /dev/null
+++ b/patches.suse/0028-Revert-btrfs-qgroups-Retry-after-commit-on-getting-E.patch
@@ -0,0 +1,98 @@
+From 0b78877a2adadc8f41f2bd959a3ffdc9c3bc0294 Mon Sep 17 00:00:00 2001
+From: Qu Wenruo <wqu@suse.com>
+Date: Tue, 12 Dec 2017 15:34:36 +0800
+Patch-mainline: v4.17-rc1
+Git-commit: 0b78877a2adadc8f41f2bd959a3ffdc9c3bc0294
+References: bsc#1031392
+Subject: [PATCH 28/28] Revert "btrfs: qgroups: Retry after commit on getting
+ EDQUOT"
+
+This reverts commit 48a89bc4f2ceab87bc858a8eb189636b09c846a7.
+
+The idea to commit transaction and free some space after hitting qgroup
+limit is good, although the problem is it can easily cause deadlocks.
+
+One deadlock example is caused by trying to flush data while still
+holding it:
+
+Call Trace:
+ __schedule+0x49d/0x10f0
+ schedule+0xc6/0x290
+ schedule_timeout+0x187/0x1c0
+ wait_for_completion+0x204/0x3a0
+ btrfs_wait_ordered_extents+0xa40/0xaf0 [btrfs]
+ qgroup_reserve+0x913/0xa10 [btrfs]
+ btrfs_qgroup_reserve_data+0x3ef/0x580 [btrfs]
+ btrfs_check_data_free_space+0x96/0xd0 [btrfs]
+ __btrfs_buffered_write+0x3ac/0xd40 [btrfs]
+ btrfs_file_write_iter+0x62a/0xba0 [btrfs]
+ __vfs_write+0x320/0x430
+ vfs_write+0x107/0x270
+ SyS_write+0xbf/0x150
+ do_syscall_64+0x1b0/0x3d0
+ entry_SYSCALL64_slow_path+0x25/0x25
+
+Another can be caused by trying to commit one transaction while nesting
+with trans handle held by ourselves:
+
+btrfs_start_transaction()
+|- btrfs_qgroup_reserve_meta_pertrans()
+ |- qgroup_reserve()
+ |- btrfs_join_transaction()
+ |- btrfs_commit_transaction()
+
+The retry is causing more problems than exppected when limit is enabled.
+At least a graceful EDQUOT is way better than deadlock.
+
+Signed-off-by: Qu Wenruo <wqu@suse.com>
+Signed-off-by: David Sterba <dsterba@suse.com>
+---
+ fs/btrfs/qgroup.c | 23 -----------------------
+ 1 file changed, 23 deletions(-)
+
+--- a/fs/btrfs/qgroup.c
++++ b/fs/btrfs/qgroup.c
+@@ -2393,7 +2393,6 @@ static int qgroup_reserve(struct btrfs_r
+ struct btrfs_fs_info *fs_info = root->fs_info;
+ u64 ref_root = root->root_key.objectid;
+ int ret = 0;
+- int retried = 0;
+ struct ulist_node *unode;
+ struct ulist_iterator uiter;
+
+@@ -2402,7 +2401,6 @@ static int qgroup_reserve(struct btrfs_r
+
+ if (num_bytes == 0)
+ return 0;
+-retry:
+ spin_lock(&fs_info->qgroup_lock);
+ quota_root = fs_info->quota_root;
+ if (!quota_root)
+@@ -2429,27 +2427,6 @@ retry:
+ qg = u64_to_ptr(unode->aux);
+
+ if (enforce && !qgroup_check_limits(qg, num_bytes)) {
+- /*
+- * Commit the tree and retry, since we may have
+- * deletions which would free up space.
+- */
+- if (!retried && qgroup_rsv_total(qg) > 0) {
+- struct btrfs_trans_handle *trans;
+-
+- spin_unlock(&fs_info->qgroup_lock);
+- ret = btrfs_start_delalloc_inodes(root, 0);
+- if (ret)
+- return ret;
+- btrfs_wait_ordered_extents(root, -1, 0, (u64)-1);
+- trans = btrfs_join_transaction(root);
+- if (IS_ERR(trans))
+- return PTR_ERR(trans);
+- ret = btrfs_commit_transaction(trans, root);
+- if (ret)
+- return ret;
+- retried++;
+- goto retry;
+- }
+ ret = -EDQUOT;
+ goto out;
+ }
diff --git a/patches.suse/0029-btrfs-qgroup-Commit-transaction-in-advance-to-reduce.patch b/patches.suse/0029-btrfs-qgroup-Commit-transaction-in-advance-to-reduce.patch
new file mode 100644
index 0000000000..ea800fb0a8
--- /dev/null
+++ b/patches.suse/0029-btrfs-qgroup-Commit-transaction-in-advance-to-reduce.patch
@@ -0,0 +1,166 @@
+From a514d63882c3d2063b21b865447266ebcb18b04c Mon Sep 17 00:00:00 2001
+From: Qu Wenruo <wqu@suse.com>
+Date: Fri, 22 Dec 2017 16:06:39 +0800
+Patch-mainline: v4.17-rc2
+Git-commit: a514d63882c3d2063b21b865447266ebcb18b04c
+References: bsc#1031392
+Subject: [PATCH 29/31] btrfs: qgroup: Commit transaction in advance to reduce
+ early EDQUOT
+
+Unlike previous method that tries to commit transaction inside
+qgroup_reserve(), this time we will try to commit transaction using
+fs_info->transaction_kthread to avoid nested transaction and no need to
+worry about locking context.
+
+Since it's an asynchronous function call and we won't wait for
+transaction commit, unlike previous method, we must call it before we
+hit the qgroup limit.
+
+So this patch will use the ratio and size of qgroup meta_pertrans
+reservation as indicator to check if we should trigger a transaction
+commit. (meta_prealloc won't be cleaned in transaction committ, it's
+useless anyway)
+
+Signed-off-by: Qu Wenruo <wqu@suse.com>
+Signed-off-by: David Sterba <dsterba@suse.com>
+---
+ fs/btrfs/ctree.h | 6 ++++++
+ fs/btrfs/disk-io.c | 2 ++
+ fs/btrfs/qgroup.c | 43 +++++++++++++++++++++++++++++++++++++++++--
+ fs/btrfs/transaction.c | 1 +
+ fs/btrfs/transaction.h | 14 ++++++++++++++
+ 5 files changed, 64 insertions(+), 2 deletions(-)
+
+--- a/fs/btrfs/ctree.h
++++ b/fs/btrfs/ctree.h
+@@ -680,6 +680,12 @@ struct btrfs_delayed_root;
+ #define BTRFS_FS_LOG1_ERR 12
+ #define BTRFS_FS_LOG2_ERR 13
+
++/*
++ * To info transaction_kthread we need an immediate commit so it doesn't
++ * need to wait for commit_interval
++ */
++#define BTRFS_FS_NEED_ASYNC_COMMIT 17
++
+ struct btrfs_fs_info {
+ u8 fsid[BTRFS_FSID_SIZE];
+ u8 chunk_tree_uuid[BTRFS_UUID_SIZE];
+--- a/fs/btrfs/disk-io.c
++++ b/fs/btrfs/disk-io.c
+@@ -1905,6 +1905,8 @@ static int transaction_kthread(void *arg
+
+ now = get_seconds();
+ if (cur->state < TRANS_STATE_BLOCKED &&
++ !test_bit(BTRFS_FS_NEED_ASYNC_COMMIT,
++ &root->fs_info->flags) &&
+ (now < cur->start_time ||
+ now - cur->start_time < root->fs_info->commit_interval)) {
+ spin_unlock(&root->fs_info->trans_lock);
+--- a/fs/btrfs/qgroup.c
++++ b/fs/btrfs/qgroup.c
+@@ -24,6 +24,7 @@
+ #include <linux/slab.h>
+ #include <linux/workqueue.h>
+ #include <linux/btrfs.h>
++#include <linux/sizes.h>
+
+ #include "ctree.h"
+ #include "transaction.h"
+@@ -2372,8 +2373,21 @@ out:
+ return ret;
+ }
+
+-static bool qgroup_check_limits(const struct btrfs_qgroup *qg, u64 num_bytes)
++/*
++ * Two limits to commit transaction in advance.
++ *
++ * For RATIO, it will be 1/RATIO of the remaining limit
++ * (excluding data and prealloc meta) as threshold.
++ * For SIZE, it will be in byte unit as threshold.
++ */
++#define QGROUP_PERTRANS_RATIO 32
++#define QGROUP_PERTRANS_SIZE SZ_32M
++static bool qgroup_check_limits(struct btrfs_fs_info *fs_info,
++ const struct btrfs_qgroup *qg, u64 num_bytes)
+ {
++ u64 limit;
++ u64 threshold;
++
+ if ((qg->lim_flags & BTRFS_QGROUP_LIMIT_MAX_RFER) &&
+ qgroup_rsv_total(qg) + (s64)qg->rfer + num_bytes > qg->max_rfer)
+ return false;
+@@ -2382,6 +2396,31 @@ static bool qgroup_check_limits(const st
+ qgroup_rsv_total(qg) + (s64)qg->excl + num_bytes > qg->max_excl)
+ return false;
+
++ /*
++ * Even if we passed the check, it's better to check if reservation
++ * for meta_pertrans is pushing us near limit.
++ * If there is too much pertrans reservation or it's near the limit,
++ * let's try commit transaction to free some, using transaction_kthread
++ */
++ if ((qg->lim_flags & (BTRFS_QGROUP_LIMIT_MAX_RFER |
++ BTRFS_QGROUP_LIMIT_MAX_EXCL))) {
++ if (qg->lim_flags & BTRFS_QGROUP_LIMIT_MAX_EXCL)
++ limit = qg->max_excl;
++ else
++ limit = qg->max_rfer;
++ threshold = (limit - qg->rsv.values[BTRFS_QGROUP_RSV_DATA] -
++ qg->rsv.values[BTRFS_QGROUP_RSV_META_PREALLOC]) /
++ QGROUP_PERTRANS_RATIO;
++ threshold = min_t(u64, threshold, QGROUP_PERTRANS_SIZE);
++
++ /*
++ * Use transaction_kthread to commit transaction, so we no
++ * longer need to bother nested transaction nor lock context.
++ */
++ if (qg->rsv.values[BTRFS_QGROUP_RSV_META_PERTRANS] > threshold)
++ btrfs_commit_transaction_locksafe(fs_info);
++ }
++
+ return true;
+ }
+
+@@ -2426,7 +2465,7 @@ static int qgroup_reserve(struct btrfs_r
+
+ qg = u64_to_ptr(unode->aux);
+
+- if (enforce && !qgroup_check_limits(qg, num_bytes)) {
++ if (enforce && !qgroup_check_limits(fs_info, qg, num_bytes)) {
+ ret = -EDQUOT;
+ goto out;
+ }
+--- a/fs/btrfs/transaction.c
++++ b/fs/btrfs/transaction.c
+@@ -2245,6 +2245,7 @@ int btrfs_commit_transaction(struct btrf
+ */
+ cur_trans->state = TRANS_STATE_COMPLETED;
+ wake_up(&cur_trans->commit_wait);
++ clear_bit(BTRFS_FS_NEED_ASYNC_COMMIT, &root->fs_info->flags);
+
+ spin_lock(&root->fs_info->trans_lock);
+ list_del_init(&cur_trans->list);
+--- a/fs/btrfs/transaction.h
++++ b/fs/btrfs/transaction.h
+@@ -185,6 +185,20 @@ static inline void btrfs_clear_skip_qgro
+ delayed_refs->qgroup_to_skip = 0;
+ }
+
++
++/*
++ * Try to commit transaction asynchronously, so this is safe to call
++ * even holding a spinlock.
++ *
++ * It's done by informing transaction_kthread to commit transaction without
++ * waiting for commit interval.
++ */
++static inline void btrfs_commit_transaction_locksafe(
++ struct btrfs_fs_info *fs_info)
++{
++ set_bit(BTRFS_FS_NEED_ASYNC_COMMIT, &fs_info->flags);
++ wake_up_process(fs_info->transaction_kthread);
++}
+ int btrfs_end_transaction(struct btrfs_trans_handle *trans,
+ struct btrfs_root *root);
+ struct btrfs_trans_handle *btrfs_start_transaction(struct btrfs_root *root,
diff --git a/patches.suse/0030-btrfs-qgroup-Use-independent-and-accurate-per-inode-.patch b/patches.suse/0030-btrfs-qgroup-Use-independent-and-accurate-per-inode-.patch
new file mode 100644
index 0000000000..af45f2702e
--- /dev/null
+++ b/patches.suse/0030-btrfs-qgroup-Use-independent-and-accurate-per-inode-.patch
@@ -0,0 +1,238 @@
+From ff6bc37eb7f6e7b052e50c13a480e1080b3ec07a Mon Sep 17 00:00:00 2001
+From: Qu Wenruo <wqu@suse.com>
+Date: Thu, 21 Dec 2017 13:42:04 +0800
+Patch-mainline: v4.17-rc2
+Git-commit: ff6bc37eb7f6e7b052e50c13a480e1080b3ec07a
+References: bsc#1031392
+Subject: [PATCH 30/31] btrfs: qgroup: Use independent and accurate per inode
+ qgroup rsv
+
+Unlike reservation calculation used in inode rsv for metadata, qgroup
+doesn't really need to care about things like csum size or extent usage
+for the whole tree COW.
+
+Qgroups care more about net change of the extent usage.
+That's to say, if we're going to insert one file extent, it will mostly
+find its place in COWed tree block, leaving no change in extent usage.
+Or causing a leaf split, resulting in one new net extent and increasing
+qgroup number by nodesize.
+Or in an even more rare case, increase the tree level, increasing qgroup
+number by 2 * nodesize.
+
+So here instead of using the complicated calculation for extent
+allocator, which cares more about accuracy and no error, qgroup doesn't
+need that over-estimated reservation.
+
+This patch will maintain 2 new members in btrfs_block_rsv structure for
+qgroup, using much smaller calculation for qgroup rsv, reducing false
+EDQUOT.
+
+Signed-off-by: David Sterba <dsterba@suse.com>
+Signed-off-by: Qu Wenruo <wqu@suse.com>
+---
+ fs/btrfs/ctree.h | 19 ++++++++++++++++
+ fs/btrfs/extent-tree.c | 57 +++++++++++++++++++++++++++++++++++++++----------
+ 2 files changed, 65 insertions(+), 11 deletions(-)
+
+--- a/fs/btrfs/ctree.h
++++ b/fs/btrfs/ctree.h
+@@ -467,6 +467,25 @@ struct btrfs_block_rsv {
+ unsigned short full;
+ unsigned short type;
+ unsigned short failfast;
++
++ /*
++ * Qgroup equivalent for @size @reserved
++ *
++ * Unlike normal @size/@reserved for inode rsv, qgroup doesn't care
++ * about things like csum size nor how many tree blocks it will need to
++ * reserve.
++ *
++ * Qgroup cares more about net change of the extent usage.
++ *
++ * So for one newly inserted file extent, in worst case it will cause
++ * leaf split and level increase, nodesize for each file extent is
++ * already too much.
++ *
++ * In short, qgroup_size/reserved is the upper limit of possible needed
++ * qgroup metadata reservation.
++ */
++ u64 qgroup_rsv_size;
++ u64 qgroup_rsv_reserved;
+ };
+
+ /*
+--- a/fs/btrfs/extent-tree.c
++++ b/fs/btrfs/extent-tree.c
+@@ -5511,14 +5511,18 @@ again:
+
+ static u64 block_rsv_release_bytes(struct btrfs_fs_info *fs_info,
+ struct btrfs_block_rsv *block_rsv,
+- struct btrfs_block_rsv *dest, u64 num_bytes)
++ struct btrfs_block_rsv *dest, u64 num_bytes,
++ u64 *qgroup_to_release_ret)
+ {
+ struct btrfs_space_info *space_info = block_rsv->space_info;
++ u64 qgroup_to_release = 0;
+ u64 ret;
+
+ spin_lock(&block_rsv->lock);
+- if (num_bytes == (u64)-1)
++ if (num_bytes == (u64)-1) {
+ num_bytes = block_rsv->size;
++ qgroup_to_release = block_rsv->qgroup_rsv_size;
++ }
+ block_rsv->size -= num_bytes;
+ if (block_rsv->reserved >= block_rsv->size) {
+ num_bytes = block_rsv->reserved - block_rsv->size;
+@@ -5527,6 +5531,13 @@ static u64 block_rsv_release_bytes(struc
+ } else {
+ num_bytes = 0;
+ }
++ if (block_rsv->qgroup_rsv_reserved >= block_rsv->qgroup_rsv_size) {
++ qgroup_to_release = block_rsv->qgroup_rsv_reserved -
++ block_rsv->qgroup_rsv_size;
++ block_rsv->qgroup_rsv_reserved = block_rsv->qgroup_rsv_size;
++ } else {
++ qgroup_to_release = 0;
++ }
+ spin_unlock(&block_rsv->lock);
+
+ ret = num_bytes;
+@@ -5549,6 +5560,8 @@ static u64 block_rsv_release_bytes(struc
+ space_info_add_old_bytes(fs_info, space_info,
+ num_bytes);
+ }
++ if (qgroup_to_release_ret)
++ *qgroup_to_release_ret = qgroup_to_release;
+ return ret;
+ }
+
+@@ -5692,17 +5705,21 @@ int btrfs_inode_rsv_refill(struct btrfs_
+ struct btrfs_root *root = inode->root;
+ struct btrfs_block_rsv *block_rsv = &inode->block_rsv;
+ u64 num_bytes = 0;
++ u64 qgroup_num_bytes = 0;
+ int ret = -ENOSPC;
+
+ spin_lock(&block_rsv->lock);
+ if (block_rsv->reserved < block_rsv->size)
+ num_bytes = block_rsv->size - block_rsv->reserved;
++ if (block_rsv->qgroup_rsv_reserved < block_rsv->qgroup_rsv_size)
++ qgroup_num_bytes = block_rsv->qgroup_rsv_size -
++ block_rsv->qgroup_rsv_reserved;
+ spin_unlock(&block_rsv->lock);
+
+ if (num_bytes == 0)
+ return 0;
+
+- ret = btrfs_qgroup_reserve_meta_prealloc(root, num_bytes, true);
++ ret = btrfs_qgroup_reserve_meta_prealloc(root, qgroup_num_bytes, true);
+ if (ret)
+ return ret;
+ ret = reserve_metadata_bytes(root, block_rsv, num_bytes, flush);
+@@ -5711,7 +5728,13 @@ int btrfs_inode_rsv_refill(struct btrfs_
+ trace_btrfs_space_reservation(root->fs_info, "delalloc",
+ btrfs_ino(&inode->vfs_inode),
+ num_bytes, 1);
+- }
++
++ /* Don't forget to increase qgroup_rsv_reserved */
++ spin_lock(&block_rsv->lock);
++ block_rsv->qgroup_rsv_reserved += qgroup_num_bytes;
++ spin_unlock(&block_rsv->lock);
++ } else
++ btrfs_qgroup_free_meta_prealloc(root, qgroup_num_bytes);
+ return ret;
+ }
+
+@@ -5732,21 +5755,24 @@ void btrfs_inode_rsv_release(struct btrf
+ struct btrfs_block_rsv *global_rsv = &fs_info->global_block_rsv;
+ struct btrfs_block_rsv *block_rsv = &inode->block_rsv;
+ u64 released = 0;
++ u64 qgroup_to_release = 0;
+
+ /*
+ * Since we statically set the block_rsv->size we just want to say we
+ * are releasing 0 bytes, and then we'll just get the reservation over
+ * the size free'd.
+ */
+- released = block_rsv_release_bytes(fs_info, block_rsv, global_rsv, 0);
++ released = block_rsv_release_bytes(fs_info, block_rsv, global_rsv, 0,
++ &qgroup_to_release);
+ if (released > 0)
+ trace_btrfs_space_reservation(fs_info, "delalloc",
+ btrfs_ino(&inode->vfs_inode),
+ released, 0);
+ if (qgroup_free)
+- btrfs_qgroup_free_meta_prealloc(inode->root, released);
++ btrfs_qgroup_free_meta_prealloc(inode->root, qgroup_to_release);
+ else
+- btrfs_qgroup_convert_reserved_meta(inode->root, released);
++ btrfs_qgroup_convert_reserved_meta(inode->root,
++ qgroup_to_release);
+ }
+
+ void btrfs_block_rsv_release(struct btrfs_root *root,
+@@ -5758,7 +5784,7 @@ void btrfs_block_rsv_release(struct btrf
+ block_rsv->space_info != global_rsv->space_info)
+ global_rsv = NULL;
+ block_rsv_release_bytes(root->fs_info, block_rsv, global_rsv,
+- num_bytes);
++ num_bytes, NULL);
+ }
+
+ static void update_global_block_rsv(struct btrfs_fs_info *fs_info)
+@@ -5840,7 +5866,7 @@ static void init_global_block_rsv(struct
+ static void release_global_block_rsv(struct btrfs_fs_info *fs_info)
+ {
+ block_rsv_release_bytes(fs_info, &fs_info->global_block_rsv, NULL,
+- (u64)-1);
++ (u64)-1, NULL);
+ WARN_ON(fs_info->trans_block_rsv.size > 0);
+ WARN_ON(fs_info->trans_block_rsv.reserved > 0);
+ WARN_ON(fs_info->chunk_block_rsv.size > 0);
+@@ -5878,7 +5904,7 @@ void btrfs_trans_release_chunk_metadata(
+ WARN_ON_ONCE(!list_empty(&trans->new_bgs));
+
+ block_rsv_release_bytes(fs_info, &fs_info->chunk_block_rsv, NULL,
+- trans->chunk_bytes_reserved);
++ trans->chunk_bytes_reserved, NULL);
+ trans->chunk_bytes_reserved = 0;
+ }
+
+@@ -5979,6 +6005,7 @@ static void btrfs_calculate_inode_block_
+ {
+ struct btrfs_block_rsv *block_rsv = &inode->block_rsv;
+ u64 reserve_size = 0;
++ u64 qgroup_rsv_size = 0;
+ u64 csum_leaves;
+ unsigned outstanding_extents;
+
+@@ -5991,9 +6018,17 @@ static void btrfs_calculate_inode_block_
+ inode->csum_bytes);
+ reserve_size += btrfs_calc_trans_metadata_size(inode->root,
+ csum_leaves);
++ /*
++ * For qgroup rsv, the calculation is very simple:
++ * account one nodesize for each outstanding extent
++ *
++ * This is overestimating in most cases.
++ */
++ qgroup_rsv_size = outstanding_extents * fs_info->tree_root->nodesize;
+
+ spin_lock(&block_rsv->lock);
+ block_rsv->size = reserve_size;
++ block_rsv->qgroup_rsv_size = qgroup_rsv_size;
+ spin_unlock(&block_rsv->lock);
+ }
+
+@@ -8340,7 +8375,7 @@ static void unuse_block_rsv(struct btrfs
+ struct btrfs_block_rsv *block_rsv, u32 blocksize)
+ {
+ block_rsv_add_bytes(block_rsv, blocksize, 0);
+- block_rsv_release_bytes(fs_info, block_rsv, NULL, 0);
++ block_rsv_release_bytes(fs_info, block_rsv, NULL, 0, NULL);
+ }
+
+ /*
diff --git a/patches.suse/0031-btrfs-delayed-inode-Remove-wrong-qgroup-meta-reserva.patch b/patches.suse/0031-btrfs-delayed-inode-Remove-wrong-qgroup-meta-reserva.patch
new file mode 100644
index 0000000000..1757f29d27
--- /dev/null
+++ b/patches.suse/0031-btrfs-delayed-inode-Remove-wrong-qgroup-meta-reserva.patch
@@ -0,0 +1,86 @@
+From f218ea6c4792e0fabba0195f2f866d0a3b58431e Mon Sep 17 00:00:00 2001
+From: Qu Wenruo <wqu@suse.com>
+Date: Tue, 17 Apr 2018 16:52:45 +0800
+Patch-mainline: v4.17-rc2
+Git-commit: f218ea6c4792e0fabba0195f2f866d0a3b58431e
+References: bsc#1031392
+Subject: [PATCH 31/31] btrfs: delayed-inode: Remove wrong qgroup meta
+ reservation calls
+
+Commit 4f5427ccce5d ("btrfs: delayed-inode: Use new qgroup meta rsv for
+delayed inode and item") merged into mainline was not latest version
+submitted to the mail list in Dec 2017.
+
+Which lacks the following fixes:
+
+1) Remove btrfs_qgroup_convert_reserved_meta() call in
+ btrfs_delayed_item_release_metadata()
+2) Remove btrfs_qgroup_reserve_meta_prealloc() call in
+ btrfs_delayed_inode_reserve_metadata()
+
+Those fixes will resolve unexpected EDQUOT problems.
+
+Fixes: 4f5427ccce5d ("btrfs: delayed-inode: Use new qgroup meta rsv for delayed inode and item")
+Signed-off-by: Qu Wenruo <wqu@suse.com>
+Signed-off-by: David Sterba <dsterba@suse.com>
+---
+ fs/btrfs/delayed-inode.c | 20 ++++++++++++++++----
+ 1 file changed, 16 insertions(+), 4 deletions(-)
+
+--- a/fs/btrfs/delayed-inode.c
++++ b/fs/btrfs/delayed-inode.c
+@@ -560,6 +560,12 @@ static int btrfs_delayed_item_reserve_me
+ dst_rsv = &root->fs_info->delayed_block_rsv;
+
+ num_bytes = btrfs_calc_trans_metadata_size(root, 1);
++
++ /*
++ * Here we migrate space rsv from transaction rsv, since have already
++ * reserved space when starting a transaction. So no need to reserve
++ * qgroup space here.
++ */
+ ret = btrfs_block_rsv_migrate(src_rsv, dst_rsv, num_bytes, 1);
+ if (!ret) {
+ trace_btrfs_space_reservation(root->fs_info, "delayed_item",
+@@ -580,7 +586,10 @@ static void btrfs_delayed_item_release_m
+ return;
+
+ rsv = &root->fs_info->delayed_block_rsv;
+- btrfs_qgroup_convert_reserved_meta(root, item->bytes_reserved);
++ /*
++ * Check btrfs_delayed_item_reserve_metadata() to see why we don't need
++ * to release/reserve qgroup space.
++ */
+ trace_btrfs_space_reservation(root->fs_info, "delayed_item",
+ item->key.objectid, item->bytes_reserved,
+ 0);
+@@ -604,9 +613,6 @@ static int btrfs_delayed_inode_reserve_m
+
+ num_bytes = btrfs_calc_trans_metadata_size(root, 1);
+
+- ret = btrfs_qgroup_reserve_meta_prealloc(root, num_bytes, true);
+- if (ret < 0)
+- return ret;
+ /*
+ * btrfs_dirty_inode will update the inode under btrfs_join_transaction
+ * which doesn't reserve space for speed. This is a problem since we
+@@ -618,6 +624,10 @@ static int btrfs_delayed_inode_reserve_m
+ */
+ if (!src_rsv || (!trans->bytes_reserved &&
+ src_rsv->type != BTRFS_BLOCK_RSV_DELALLOC)) {
++ ret = btrfs_qgroup_reserve_meta_prealloc(root, root->nodesize,
++ true);
++ if (ret < 0)
++ return ret;
+ ret = btrfs_block_rsv_add(root, dst_rsv, num_bytes,
+ BTRFS_RESERVE_NO_FLUSH);
+ /*
+@@ -636,6 +646,8 @@ static int btrfs_delayed_inode_reserve_m
+ "delayed_inode",
+ btrfs_ino(inode),
+ num_bytes, 1);
++ } else {
++ btrfs_qgroup_free_meta_prealloc(root, root->nodesize);
+ }
+ return ret;
+ }
diff --git a/patches.suse/btrfs-8888-add-allow_unsupported-module-parameter.patch b/patches.suse/btrfs-8888-add-allow_unsupported-module-parameter.patch
index 047fc8959a..12f6fa6881 100644
--- a/patches.suse/btrfs-8888-add-allow_unsupported-module-parameter.patch
+++ b/patches.suse/btrfs-8888-add-allow_unsupported-module-parameter.patch
@@ -21,11 +21,11 @@ Current:
Signed-off-by: David Sterba <dsterba@suse.cz>
---
- fs/btrfs/ctree.h | 7 +++++++
+ fs/btrfs/ctree.h | 8 ++++++++
fs/btrfs/disk-io.c | 15 +++++++++++++++
fs/btrfs/ioctl.c | 8 +++++++-
fs/btrfs/super.c | 20 ++++++++++++++++++++
- 4 files changed, 49 insertions(+), 1 deletion(-)
+ 4 files changed, 50 insertions(+), 1 deletion(-)
--- a/fs/btrfs/ctree.h
+++ b/fs/btrfs/ctree.h
@@ -37,10 +37,11 @@ Signed-off-by: David Sterba <dsterba@suse.cz>
#include "extent_io.h"
#include "extent_map.h"
#include "async-thread.h"
-@@ -3555,4 +3556,10 @@ static inline int btrfs_test_is_dummy_ro
- return 0;
+@@ -3620,4 +3621,11 @@ static inline int btrfs_is_testing(struc
+ #endif
+ return 0;
}
-
++
+/*
+ * Module parameter
+ */
@@ -50,7 +51,7 @@ Signed-off-by: David Sterba <dsterba@suse.cz>
#endif
--- a/fs/btrfs/disk-io.c
+++ b/fs/btrfs/disk-io.c
-@@ -2797,6 +2797,14 @@ int open_ctree(struct super_block *sb,
+@@ -2750,6 +2750,14 @@ int open_ctree(struct super_block *sb,
if (btrfs_super_flags(disk_super) & BTRFS_SUPER_FLAG_ERROR)
set_bit(BTRFS_FS_STATE_ERROR, &fs_info->fs_state);
@@ -65,7 +66,7 @@ Signed-off-by: David Sterba <dsterba@suse.cz>
/*
* run through our array of backup supers and setup
* our ring pointer to the oldest one
-@@ -2863,6 +2871,13 @@ int open_ctree(struct super_block *sb,
+@@ -2816,6 +2824,13 @@ int open_ctree(struct super_block *sb,
goto fail_alloc;
}
@@ -81,7 +82,7 @@ Signed-off-by: David Sterba <dsterba@suse.cz>
* update the flag.
--- a/fs/btrfs/ioctl.c
+++ b/fs/btrfs/ioctl.c
-@@ -5617,6 +5617,7 @@ long btrfs_ioctl(struct file *file, unsi
+@@ -5630,6 +5630,7 @@ long btrfs_ioctl(struct file *file, unsi
{
struct btrfs_root *root = BTRFS_I(file_inode(file))->root;
void __user *argp = (void __user *)arg;
@@ -89,7 +90,7 @@ Signed-off-by: David Sterba <dsterba@suse.cz>
switch (cmd) {
case FS_IOC_GETFLAGS:
-@@ -5737,6 +5738,11 @@ long btrfs_ioctl(struct file *file, unsi
+@@ -5750,6 +5751,11 @@ long btrfs_ioctl(struct file *file, unsi
case BTRFS_IOC_QUOTA_RESCAN_WAIT:
return btrfs_ioctl_quota_rescan_wait(file, argp);
case BTRFS_IOC_DEV_REPLACE:
@@ -101,7 +102,7 @@ Signed-off-by: David Sterba <dsterba@suse.cz>
return btrfs_ioctl_dev_replace(root, argp);
case BTRFS_IOC_GET_FSLABEL:
return btrfs_ioctl_get_fslabel(file, argp);
-@@ -5752,7 +5758,7 @@ long btrfs_ioctl(struct file *file, unsi
+@@ -5765,7 +5771,7 @@ long btrfs_ioctl(struct file *file, unsi
return btrfs_ioctl_set_features(file, argp);
}
@@ -120,7 +121,7 @@ Signed-off-by: David Sterba <dsterba@suse.cz>
#include <linux/buffer_head.h>
#include <linux/fs.h>
#include <linux/pagemap.h>
-@@ -64,6 +65,8 @@
+@@ -65,6 +66,8 @@
#define CREATE_TRACE_POINTS
#include <trace/events/btrfs.h>
@@ -129,7 +130,7 @@ Signed-off-by: David Sterba <dsterba@suse.cz>
static const struct super_operations btrfs_super_ops;
static struct file_system_type btrfs_fs_type;
-@@ -663,6 +666,11 @@ int btrfs_parse_options(struct btrfs_roo
+@@ -667,6 +670,11 @@ int btrfs_parse_options(struct btrfs_roo
"disabling disk space caching");
break;
case Opt_inode_cache:
@@ -141,7 +142,7 @@ Signed-off-by: David Sterba <dsterba@suse.cz>
btrfs_set_pending_and_info(info, INODE_MAP_CACHE,
"enabling inode map caching");
break;
-@@ -684,6 +692,11 @@ int btrfs_parse_options(struct btrfs_roo
+@@ -688,6 +696,11 @@ int btrfs_parse_options(struct btrfs_roo
btrfs_clear_opt(info->mount_opt, ENOSPC_DEBUG);
break;
case Opt_defrag:
@@ -153,7 +154,7 @@ Signed-off-by: David Sterba <dsterba@suse.cz>
btrfs_set_and_info(root, AUTO_DEFRAG,
"enabling auto defrag");
break;
-@@ -1758,6 +1771,13 @@ static int btrfs_remount(struct super_bl
+@@ -1767,6 +1780,13 @@ static int btrfs_remount(struct super_bl
ret = -EACCES;
goto restore;
}
diff --git a/patches.suse/btrfs-add-wrapper-for-counting-BTRFS_MAX_EXTENT_SIZE.patch b/patches.suse/btrfs-add-wrapper-for-counting-BTRFS_MAX_EXTENT_SIZE.patch
new file mode 100644
index 0000000000..e6be38349a
--- /dev/null
+++ b/patches.suse/btrfs-add-wrapper-for-counting-BTRFS_MAX_EXTENT_SIZE.patch
@@ -0,0 +1,163 @@
+From 823bb20ab47071dc8a98acf272a470ccdcfcf6d1 Mon Sep 17 00:00:00 2001
+From: David Sterba <dsterba@suse.com>
+Date: Wed, 4 Jan 2017 11:09:51 +0100
+Patch-mainline: v4.14
+Git-commit: 823bb20ab47071dc8a98acf272a470ccdcfcf6d1
+References: dependency for bsc#1031392
+Subject: [PATCH] btrfs: add wrapper for counting BTRFS_MAX_EXTENT_SIZE
+
+The expression is open-coded in several places, this asks for a wrapper.
+As we know the MAX_EXTENT fits to u32, we can use the appropirate
+division helper. This cascades to the result type updates.
+
+Compiler is clever enough to use shift instead of integer division, so
+there's no change in the generated assembly.
+
+Signed-off-by: David Sterba <dsterba@suse.com>
+---
+ fs/btrfs/ctree.h | 8 ++++++++
+ fs/btrfs/extent-tree.c | 12 ++++--------
+ fs/btrfs/inode.c | 34 +++++++++++-----------------------
+ 3 files changed, 23 insertions(+), 31 deletions(-)
+
+--- a/fs/btrfs/ctree.h
++++ b/fs/btrfs/ctree.h
+@@ -99,6 +99,14 @@ static int btrfs_csum_sizes[] = { 4 };
+
+ #define BTRFS_MAX_EXTENT_SIZE (128 * 1024 * 1024)
+
++/*
++ * Count how many BTRFS_MAX_EXTENT_SIZE cover the @size
++ */
++static inline u32 count_max_extents(u64 size)
++{
++ return div_u64(size + BTRFS_MAX_EXTENT_SIZE - 1, BTRFS_MAX_EXTENT_SIZE);
++}
++
+ struct btrfs_mapping_tree {
+ struct extent_map_tree map_tree;
+ };
+--- a/fs/btrfs/extent-tree.c
++++ b/fs/btrfs/extent-tree.c
+@@ -5908,11 +5908,9 @@ static unsigned drop_outstanding_extent(
+ {
+ unsigned drop_inode_space = 0;
+ unsigned dropped_extents = 0;
+- unsigned num_extents = 0;
++ unsigned num_extents;
+
+- num_extents = (unsigned)div64_u64(num_bytes +
+- BTRFS_MAX_EXTENT_SIZE - 1,
+- BTRFS_MAX_EXTENT_SIZE);
++ num_extents = count_max_extents(num_bytes);
+ ASSERT(num_extents);
+ ASSERT(BTRFS_I(inode)->outstanding_extents >= num_extents);
+ BTRFS_I(inode)->outstanding_extents -= num_extents;
+@@ -5988,7 +5986,7 @@ int btrfs_delalloc_reserve_metadata(stru
+ struct btrfs_block_rsv *block_rsv = &root->fs_info->delalloc_block_rsv;
+ u64 to_reserve = 0;
+ u64 csum_bytes;
+- unsigned nr_extents = 0;
++ unsigned nr_extents;
+ enum btrfs_reserve_flush_enum flush = BTRFS_RESERVE_FLUSH_ALL;
+ int ret = 0;
+ bool delalloc_lock = true;
+@@ -6021,9 +6019,7 @@ int btrfs_delalloc_reserve_metadata(stru
+ num_bytes = ALIGN(num_bytes, root->sectorsize);
+
+ spin_lock(&BTRFS_I(inode)->lock);
+- nr_extents = (unsigned)div64_u64(num_bytes +
+- BTRFS_MAX_EXTENT_SIZE - 1,
+- BTRFS_MAX_EXTENT_SIZE);
++ nr_extents = count_max_extents(num_bytes);
+ BTRFS_I(inode)->outstanding_extents += nr_extents;
+
+ nr_extents = 0;
+--- a/fs/btrfs/inode.c
++++ b/fs/btrfs/inode.c
+@@ -1634,7 +1634,7 @@ static void btrfs_split_extent_hook(stru
+
+ size = orig->end - orig->start + 1;
+ if (size > BTRFS_MAX_EXTENT_SIZE) {
+- u64 num_extents;
++ u32 num_extents;
+ u64 new_size;
+
+ /*
+@@ -1642,13 +1642,10 @@ static void btrfs_split_extent_hook(stru
+ * applies here, just in reverse.
+ */
+ new_size = orig->end - split + 1;
+- num_extents = div64_u64(new_size + BTRFS_MAX_EXTENT_SIZE - 1,
+- BTRFS_MAX_EXTENT_SIZE);
++ num_extents = count_max_extents(new_size);
+ new_size = split - orig->start;
+- num_extents += div64_u64(new_size + BTRFS_MAX_EXTENT_SIZE - 1,
+- BTRFS_MAX_EXTENT_SIZE);
+- if (div64_u64(size + BTRFS_MAX_EXTENT_SIZE - 1,
+- BTRFS_MAX_EXTENT_SIZE) >= num_extents)
++ num_extents += count_max_extents(new_size);
++ if (count_max_extents(size) >= num_extents)
+ return;
+ }
+
+@@ -1668,7 +1665,7 @@ static void btrfs_merge_extent_hook(stru
+ struct extent_state *other)
+ {
+ u64 new_size, old_size;
+- u64 num_extents;
++ u32 num_extents;
+
+ /* not delalloc, ignore it */
+ if (!(other->state & EXTENT_DELALLOC))
+@@ -1706,14 +1703,10 @@ static void btrfs_merge_extent_hook(stru
+ * this case.
+ */
+ old_size = other->end - other->start + 1;
+- num_extents = div64_u64(old_size + BTRFS_MAX_EXTENT_SIZE - 1,
+- BTRFS_MAX_EXTENT_SIZE);
++ num_extents = count_max_extents(old_size);
+ old_size = new->end - new->start + 1;
+- num_extents += div64_u64(old_size + BTRFS_MAX_EXTENT_SIZE - 1,
+- BTRFS_MAX_EXTENT_SIZE);
+-
+- if (div64_u64(new_size + BTRFS_MAX_EXTENT_SIZE - 1,
+- BTRFS_MAX_EXTENT_SIZE) >= num_extents)
++ num_extents += count_max_extents(old_size);
++ if (count_max_extents(new_size) >= num_extents)
+ return;
+
+ spin_lock(&BTRFS_I(inode)->lock);
+@@ -1815,8 +1808,7 @@ static void btrfs_clear_bit_hook(struct
+ unsigned *bits)
+ {
+ u64 len = state->end + 1 - state->start;
+- u64 num_extents = div64_u64(len + BTRFS_MAX_EXTENT_SIZE -1,
+- BTRFS_MAX_EXTENT_SIZE);
++ u32 num_extents = count_max_extents(len);
+
+ spin_lock(&BTRFS_I(inode)->lock);
+ if ((state->state & EXTENT_DEFRAG) && (*bits & EXTENT_DEFRAG))
+@@ -7658,10 +7650,8 @@ static void adjust_dio_outstanding_exten
+ struct btrfs_dio_data *dio_data,
+ const u64 len)
+ {
+- unsigned num_extents;
++ unsigned num_extents = count_max_extents(len);
+
+- num_extents = (unsigned) div64_u64(len + BTRFS_MAX_EXTENT_SIZE - 1,
+- BTRFS_MAX_EXTENT_SIZE);
+ /*
+ * If we have an outstanding_extents count still set then we're
+ * within our reservation, otherwise we need to adjust our inode
+@@ -8728,9 +8718,7 @@ static ssize_t btrfs_direct_IO(struct ki
+ offset, count);
+ if (ret)
+ goto out;
+- dio_data.outstanding_extents = div64_u64(count +
+- BTRFS_MAX_EXTENT_SIZE - 1,
+- BTRFS_MAX_EXTENT_SIZE);
++ dio_data.outstanding_extents = count_max_extents(count);
+
+ /*
+ * We need to know how many extents we reserved so that we can
diff --git a/patches.suse/btrfs-qgroups-opencode-qgroup_free-helper.patch b/patches.suse/btrfs-qgroups-opencode-qgroup_free-helper.patch
new file mode 100644
index 0000000000..fcb7b058b6
--- /dev/null
+++ b/patches.suse/btrfs-qgroups-opencode-qgroup_free-helper.patch
@@ -0,0 +1,71 @@
+From 0b08e1f4f7b7af719500f5f37a60c342ba812f69 Mon Sep 17 00:00:00 2001
+From: David Sterba <dsterba@suse.com>
+Date: Mon, 13 Feb 2017 14:24:35 +0100
+Patch-mainline: v4.11
+Git-commit: 0b08e1f4f7b7af719500f5f37a60c342ba812f69
+References: dependency for bsc#1031392
+Subject: [PATCH 8/9] btrfs: qgroups: opencode qgroup_free helper
+
+The helper name is not too helpful and is just wrapping a simple call.
+
+Signed-off-by: David Sterba <dsterba@suse.com>
+Signed-off-by: Qu Wenruo <wqu@suse.com>
+---
+ fs/btrfs/qgroup.c | 18 +++++++++---------
+ 1 file changed, 9 insertions(+), 9 deletions(-)
+
+--- a/fs/btrfs/qgroup.c
++++ b/fs/btrfs/qgroup.c
+@@ -2487,11 +2487,6 @@ out:
+ spin_unlock(&fs_info->qgroup_lock);
+ }
+
+-static inline void qgroup_free(struct btrfs_root *root, u64 num_bytes)
+-{
+- return btrfs_qgroup_free_refroot(root->fs_info, root->objectid,
+- num_bytes);
+-}
+ void assert_qgroups_uptodate(struct btrfs_trans_handle *trans)
+ {
+ if (list_empty(&trans->qgroup_ref_list) && !trans->delayed_ref_elem.seq)
+@@ -2988,7 +2983,9 @@ static int __btrfs_qgroup_release_data(s
+ goto out;
+
+ if (free) {
+- qgroup_free(BTRFS_I(inode)->root, changeset.bytes_changed);
++ btrfs_qgroup_free_refroot(BTRFS_I(inode)->root->fs_info,
++ BTRFS_I(inode)->root->objectid,
++ changeset.bytes_changed);
+ trace_op = QGROUP_FREE;
+ }
+ trace_btrfs_qgroup_release_data(inode, start, len,
+@@ -3069,7 +3066,7 @@ void btrfs_qgroup_free_meta_all(struct b
+ reserved = atomic64_xchg(&root->qgroup_meta_rsv, 0);
+ if (reserved == 0)
+ return;
+- qgroup_free(root, reserved);
++ btrfs_qgroup_free_refroot(root->fs_info, root->objectid, reserved);
+ }
+
+ void btrfs_qgroup_free_meta(struct btrfs_root *root, int num_bytes)
+@@ -3081,7 +3078,7 @@ void btrfs_qgroup_free_meta(struct btrfs
+ BUG_ON(num_bytes != round_down(num_bytes, root->nodesize));
+ WARN_ON(atomic64_read(&root->qgroup_meta_rsv) < num_bytes);
+ atomic64_sub(num_bytes, &root->qgroup_meta_rsv);
+- qgroup_free(root, num_bytes);
++ btrfs_qgroup_free_refroot(root->fs_info, root->objectid, num_bytes);
+ }
+
+ /*
+@@ -3107,7 +3104,10 @@ void btrfs_qgroup_check_reserved_leak(st
+ "leaking qgroup reserved space, ino: %lu, start: %llu, end: %llu",
+ inode->i_ino, unode->val, unode->aux);
+ }
+- qgroup_free(BTRFS_I(inode)->root, changeset.bytes_changed);
++ btrfs_qgroup_free_refroot(BTRFS_I(inode)->root->fs_info,
++ BTRFS_I(inode)->root->objectid,
++ changeset.bytes_changed);
++
+ }
+ extent_changeset_release(&changeset);
+ }
diff --git a/patches.suse/hwrng-core-document-the-quality-field.patch b/patches.suse/hwrng-core-document-the-quality-field.patch
new file mode 100644
index 0000000000..da4b4ae8b5
--- /dev/null
+++ b/patches.suse/hwrng-core-document-the-quality-field.patch
@@ -0,0 +1,61 @@
+From: "Michael S. Tsirkin" <mst@redhat.com>
+Date: Tue, 25 Sep 2018 12:35:18 -0400
+Subject: hwrng: core - document the quality field
+Git-commit: fae29f135ef4a86228d3ce13b61babf0d3031118
+Patch-mainline: v4.20-rc1
+References: git-fixes
+
+quality field is currently documented as being 'per mill'. In fact the
+math involved is:
+
+ add_hwgenerator_randomness((void *)rng_fillbuf, rc,
+ rc * current_quality * 8 >> 10);
+
+thus the actual definition is "bits of entropy per 1024 bits of input".
+
+The current documentation seems to have confused multiple people
+in the past, let's fix the documentation to match code.
+
+An alternative is to change core to match driver expectations, replacing
+ rc * current_quality * 8 >> 10
+with
+ rc * current_quality / 1000
+but that has performance costs, so probably isn't a good option.
+
+Fixes: 0f734e6e768 ("hwrng: add per-device entropy derating")
+Reported-by: "Dr. David Alan Gilbert" <dgilbert@redhat.com>
+Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
+Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
+Signed-off-by: Jiri Slaby <jslaby@suse.cz>
+---
+ drivers/char/hw_random/core.c | 4 ++--
+ include/linux/hw_random.h | 3 ++-
+ 2 files changed, 4 insertions(+), 3 deletions(-)
+
+--- a/drivers/char/hw_random/core.c
++++ b/drivers/char/hw_random/core.c
+@@ -65,10 +65,10 @@ static unsigned short default_quality; /
+
+ module_param(current_quality, ushort, 0644);
+ MODULE_PARM_DESC(current_quality,
+- "current hwrng entropy estimation per mill");
++ "current hwrng entropy estimation per 1024 bits of input");
+ module_param(default_quality, ushort, 0644);
+ MODULE_PARM_DESC(default_quality,
+- "default entropy content of hwrng per mill");
++ "default entropy content of hwrng per 1024 bits of input");
+
+ static void drop_current_rng(void);
+ static int hwrng_init(struct hwrng *rng);
+--- a/include/linux/hw_random.h
++++ b/include/linux/hw_random.h
+@@ -32,7 +32,8 @@
+ * into the buffer. The buffer is aligned for any type.
+ * @priv: Private data, for use by the RNG driver.
+ * @quality: Estimation of true entropy in RNG's bitstream
+- * (per mill).
++ * (in bits of entropy per 1024 bits of input;
++ * valid values: 1 to 1024, or 0 for unknown).
+ */
+ struct hwrng {
+ const char *name;
diff --git a/patches.suse/irq_data_get_effective_affinity_mask.patch b/patches.suse/irq_data_get_effective_affinity_mask.patch
new file mode 100644
index 0000000000..b5443f127c
--- /dev/null
+++ b/patches.suse/irq_data_get_effective_affinity_mask.patch
@@ -0,0 +1,38 @@
+From: Dexuan Cui <decui@microsoft.com>
+Date: Mon, 29 Oct 2018 23:18:48 -0700
+Subject: x86/irq: implement irq_data_get_effective_affinity_mask() for v4.12
+Patch-mainline: never, base kernel too old
+References: bsc#1109772
+
+See __assign_irq_vector():
+ cpumask_copy(d->domain, vector_cpumask);
+
+The function is required by Hyper-V pci-hyperv driver.
+Signed-off-by: Dexuan Cui <decui@microsoft.com>
+Signed-off-by: Olaf Hering <ohering@suse.de>
+--- a/arch/x86/kernel/apic/vector.c
++++ b/arch/x86/kernel/apic/vector.c
+@@ -74,6 +74,13 @@ struct irq_cfg *irq_cfg(unsigned int irq
+ return irqd_cfg(irq_get_irq_data(irq));
+ }
+
++struct cpumask *irq_data_get_effective_affinity_mask(struct irq_data *d)
++{
++ struct apic_chip_data *data = apic_chip_data(d);
++ return data->domain;
++}
++EXPORT_SYMBOL_GPL(irq_data_get_effective_affinity_mask);
++
+ static struct apic_chip_data *alloc_apic_chip_data(int node)
+ {
+ struct apic_chip_data *data;
+--- a/include/linux/irq.h
++++ b/include/linux/irq.h
+@@ -745,6 +745,7 @@ static inline struct cpumask *irq_get_af
+ return d ? d->common->affinity : NULL;
+ }
+
++struct cpumask *irq_data_get_effective_affinity_mask(struct irq_data *d);
+ static inline struct cpumask *irq_data_get_affinity_mask(struct irq_data *d)
+ {
+ return d->common->affinity;
diff --git a/patches.suse/msft-hv-1545-PCI-hv-Use-effective-affinity-mask.patch b/patches.suse/msft-hv-1545-PCI-hv-Use-effective-affinity-mask.patch
index 481e030d7f..cf8b58a23b 100644
--- a/patches.suse/msft-hv-1545-PCI-hv-Use-effective-affinity-mask.patch
+++ b/patches.suse/msft-hv-1545-PCI-hv-Use-effective-affinity-mask.patch
@@ -37,7 +37,7 @@ diff --git a/drivers/pci/host/pci-hyperv.c b/drivers/pci/host/pci-hyperv.c
u64 res;
- dest = irq_data_get_affinity_mask(data);
-+ dest = irq_data_get_affinity_mask(data);
++ dest = irq_data_get_effective_affinity_mask(data);
pdev = msi_desc_to_pci_dev(msi_desc);
pbus = pdev->bus;
hbus = container_of(pbus->sysdata, struct hv_pcibus_device, sysdata);
@@ -53,7 +53,7 @@ diff --git a/drivers/pci/host/pci-hyperv.c b/drivers/pci/host/pci-hyperv.c
int ret;
pdev = msi_desc_to_pci_dev(irq_data_get_msi_desc(data));
-+ dest = irq_data_get_affinity_mask(data);
++ dest = irq_data_get_effective_affinity_mask(data);
pbus = pdev->bus;
hbus = container_of(pbus->sysdata, struct hv_pcibus_device, sysdata);
hpdev = get_pcichild_wslot(hbus, devfn_to_wslot(pdev->devfn));
diff --git a/patches.suse/msft-hv-1766-hv_netvsc-fix-vf-serial-matching-with-pci-slot-info.patch b/patches.suse/msft-hv-1766-hv_netvsc-fix-vf-serial-matching-with-pci-slot-info.patch
index b9f06f8fce..2f9f5621fb 100644
--- a/patches.suse/msft-hv-1766-hv_netvsc-fix-vf-serial-matching-with-pci-slot-info.patch
+++ b/patches.suse/msft-hv-1766-hv_netvsc-fix-vf-serial-matching-with-pci-slot-info.patch
@@ -1,8 +1,7 @@
From: Haiyang Zhang <haiyangz@microsoft.com>
Date: Mon, 15 Oct 2018 19:06:15 +0000
-Patch-mainline: Queued
+Patch-mainline: v4.20-rc1
Subject: hv_netvsc: fix vf serial matching with pci slot info
-Git-repo: git://git.kernel.org/pub/scm/linux/kernel/git/davem/net-next.git
Git-commit: 005479556197f80139771960dda0dfdcd2d2aad5
References: bug#1109038
diff --git a/patches.suse/rpmsg-Correct-support-for-MODULE_DEVICE_TABLE.patch b/patches.suse/rpmsg-Correct-support-for-MODULE_DEVICE_TABLE.patch
new file mode 100644
index 0000000000..9ca189e3d8
--- /dev/null
+++ b/patches.suse/rpmsg-Correct-support-for-MODULE_DEVICE_TABLE.patch
@@ -0,0 +1,52 @@
+From: "Andrew F. Davis" <afd@ti.com>
+Date: Sat, 21 Apr 2018 18:55:29 -0500
+Subject: rpmsg: Correct support for MODULE_DEVICE_TABLE()
+Git-commit: 5b7d127726de6eed4b900bc3bbb167837690818f
+Patch-mainline: v4.18-rc1
+References: git-fixes
+
+Due to missing a missing entry in file2alias.c MODULE_DEVICE_TABLE() are
+not generating the proper module aliases. Add the needed entry here.
+
+Fixes: bcabbccabffe ("rpmsg: add virtio-based remote processor messaging bus")
+Reported-by: Suman Anna <s-anna@ti.com>
+Signed-off-by: Andrew F. Davis <afd@ti.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+Signed-off-by: Jiri Slaby <jslaby@suse.cz>
+---
+ scripts/mod/devicetable-offsets.c | 3 +++
+ scripts/mod/file2alias.c | 11 +++++++++++
+ 2 files changed, 14 insertions(+)
+
+--- a/scripts/mod/devicetable-offsets.c
++++ b/scripts/mod/devicetable-offsets.c
+@@ -138,6 +138,9 @@ int main(void)
+ DEVID(hv_vmbus_device_id);
+ DEVID_FIELD(hv_vmbus_device_id, guid);
+
++ DEVID(rpmsg_device_id);
++ DEVID_FIELD(rpmsg_device_id, name);
++
+ DEVID(i2c_device_id);
+ DEVID_FIELD(i2c_device_id, name);
+
+--- a/scripts/mod/file2alias.c
++++ b/scripts/mod/file2alias.c
+@@ -926,6 +926,17 @@ static int do_vmbus_entry(const char *fi
+ }
+ ADD_TO_DEVTABLE("vmbus", hv_vmbus_device_id, do_vmbus_entry);
+
++/* Looks like: rpmsg:S */
++static int do_rpmsg_entry(const char *filename, void *symval,
++ char *alias)
++{
++ DEF_FIELD_ADDR(symval, rpmsg_device_id, name);
++ sprintf(alias, RPMSG_DEVICE_MODALIAS_FMT, *name);
++
++ return 1;
++}
++ADD_TO_DEVTABLE("rpmsg", rpmsg_device_id, do_rpmsg_entry);
++
+ /* Looks like: i2c:S */
+ static int do_i2c_entry(const char *filename, void *symval,
+ char *alias)
diff --git a/rpm/apply-patches b/rpm/apply-patches
index 4a75d05b16..350653573a 100755
--- a/rpm/apply-patches
+++ b/rpm/apply-patches
@@ -38,7 +38,7 @@ fi
echo "set -ex"
"$DIR"/guards "$@" <"$series" | \
if $vanilla; then
- egrep '^patches\.(kernel\.org|rpmify)/'
+ sed -rn '/^patches\.(kernel\.org|rpmify)\//p'
else
cat
fi |\
diff --git a/rpm/arch-symbols b/rpm/arch-symbols
index 5032d78033..6a80fdd35b 100755
--- a/rpm/arch-symbols
+++ b/rpm/arch-symbols
@@ -1,4 +1,4 @@
-#!/bin/sh
+#!/bin/bash
#############################################################################
# Copyright (c) 2003-2005,2009 Novell, Inc.
diff --git a/rpm/check-for-config-changes b/rpm/check-for-config-changes
index 9fa6dca8ee..c409f2059c 100755
--- a/rpm/check-for-config-changes
+++ b/rpm/check-for-config-changes
@@ -2,8 +2,8 @@
# lines 4 contains a timestamp...
differences="$(
- diff -bU0 <(sed -e '/^# .* is not set$/p' -e '/^$\|^#/d' "$1" | sort) \
- <(sed -e '/^# .* is not set$/p' -e '/^$\|^#/d' "$2" | sort) \
+ diff -bU0 <(sed -e '/CONFIG_GCC_VERSION/ d' -e '/^# .* is not set$/p' -e '/^$\|^#/d' "$1" | sort) \
+ <(sed -e '/CONFIG_GCC_VERSION/ d' -e '/^# .* is not set$/p' -e '/^$\|^#/d' "$2" | sort) \
| grep '^[-+][^-+]'
)" || true
if [ -n "$differences" ]; then
diff --git a/rpm/check-module-license b/rpm/check-module-license
new file mode 100755
index 0000000000..9910deec18
--- /dev/null
+++ b/rpm/check-module-license
@@ -0,0 +1,12 @@
+#!/bin/sh
+
+rc=0
+for file in $(find "$@" -name '*.ko'); do
+ l=$(/sbin/modinfo -F license "$file")
+ if [ -z "$l" ]; then
+ echo "ERROR: No license is included for module ${file##*/lib/modules/}"
+ rc=1
+ fi
+done
+
+exit $rc
diff --git a/rpm/constraints.in b/rpm/constraints.in
index 435fc5b339..736525f066 100644
--- a/rpm/constraints.in
+++ b/rpm/constraints.in
@@ -1,5 +1,5 @@
<constraints>
- <!-- Default 20GB for binary packages -->
+ <!-- Default 25GB for binary packages -->
<overwrite>
<conditions>
@BINARY_PACKAGES_XML@
@@ -23,6 +23,9 @@
<disk>
<size unit="G">35</size>
</disk>
+ <physicalmemory>
+ <size unit="G">8</size>
+ </physicalmemory>
</hardware>
</overwrite>
@@ -77,6 +80,19 @@
</hardware>
</overwrite>
+ <!-- 2 CPUs for binary packages on ARM -->
+ <overwrite>
+ <conditions>
+ <arch>aarch64</arch>
+ <arch>armv6l</arch>
+ <arch>armv7l</arch>
+@BINARY_PACKAGES_XML@
+ </conditions>
+ <hardware>
+ <processors>2</processors>
+ </hardware>
+ </overwrite>
+
<overwrite>
<conditions>
<arch>i586</arch>
diff --git a/rpm/gitlog-excludes b/rpm/gitlog-excludes
index f4ae96abaf..111ca11407 100644
--- a/rpm/gitlog-excludes
+++ b/rpm/gitlog-excludes
@@ -1,2 +1,40 @@
595f160321e06d1792fd1987a8ea97c5c93a8256
31f2eb8b428e655fc056d243e394348b7c327548
+48b03c4e62a9b45d666136bef7ab01aac892108e
+85c92724f44a568ef39d6e7df732a1345b63e8b4
+d14f1529fa67119cb93798cc91ddd2a47226872f
+ae8069ff6c43497122b072bcea1e64e52b2a9e26
+d6435125446d740016904abe30a60611549ae812
+3371adc859f32dba535517ed66ad379f1a05fe21
+6fcec9a71462b054c9b9f6d247b3c65ff7cb6ebd
+1f7acca662ec7deb151fdd39bbe2784373043ff2
+0e53042c6f36c7a7a141860835aa2c308586cf2b
+e35f14af9c15ba7c53ea7630853daed7a55cd8b1
+2cb2beca83bb644337d99fbb977abf7f31af43b4
+f70bab5f4adb2d49b6af8ef185578b38ac937da2
+0b1b4d3e0a5a709c95e16179067ed55dafeb51a9
+83d831c0d14cc0af8578fa845088a5f242de13f9
+d7695e11f346824b0d559455412603c579daa2f1
+967b28b8255cf2b2f8b0d34d830ccb2dbb2484fe
+10a8bc496a553b8069d490a8ae7508bdb19f58d9
+f5686d2353c4c845e1adab662144df5a00404667
+679f5c5e0ef65085e12797e831a5e981e141679f
+0d7b4b3f948c2efb67b7d1b95b5e1dcae225991c
+4b5450ac9f2dc884a5bc81c86106dbf088721249
+4ad1ede9c771c1f057f3377d7ff36116916f490b
+0e5fcf9e25045ccef304ad60904e35480dacdfdf
+0ed191d3ab7fd64ee69e4b67aef1b99e88159e48
+cad1ef90ba8c995bf863e0bfc0bacff55f904410
+4e37db7104a04527ea0398fcbb8fa3c41d8c32c5
+c94e6466619c1f77e76c8656ae3126a6ce26dbb9
+4de517c7a247281aa5ecf0daeac9470b7a046ec6
+44cf2d61d0497d2f1e45d6361b275361c94d0f03
+f3a9899f8c180f0455c6bcc725496c4a09ed6958
+cdcab939827d1646238a4d261e4ebbe3bec6cb21
+327c01ea547b9894f4dbcaf34ba65f7b5d7fd981
+814c4ecad8bddb0ed0e47b24d87bd072e5dcd1ea
+26739251057aa234987f24e95559e4ab2d1fc6d7
+c7605f2e61a60d90e8a8d2f7fb186fc619e52e89
+9e33f22b303dc2bdbc681bc8c2329ccf4c6a17c5
+7975919af1f23d36fe37b2fe8fba3fbb92f98798
+
diff --git a/rpm/group-source-files.pl b/rpm/group-source-files.pl
index e585206d5e..768ecffc44 100755
--- a/rpm/group-source-files.pl
+++ b/rpm/group-source-files.pl
@@ -40,6 +40,7 @@ sub scan
m{^\Q$loc\E/arch/arm/[^/]+/include/mach\b} ||
m{^\Q$loc\E/arch/arm/[^/]+/include/plat\b} ||
m{^\Q$loc\E/arch/[^/]+/scripts\b} ||
+ m{^\Q$loc\E/arch/[^/]+/tools\b} ||
m{^\Q$loc\E/include/[^/]+\b} ||
m{^\Q$loc\E/scripts\b};
if (substr($_, 0, 1) ne "/") {
diff --git a/rpm/kabi.pl b/rpm/kabi.pl
index 20ced4c165..bce16b1a65 100755
--- a/rpm/kabi.pl
+++ b/rpm/kabi.pl
@@ -60,7 +60,7 @@ sub load_symvers {
$errors++;
next;
}
- my $new = { crc => $l[0], mod => $l[2] };
+ my $new = { crc => $l[0], mod => $l[2], type => $l[3] };
$res{$l[1]} = $new;
}
if (!%res) {
@@ -71,9 +71,35 @@ sub load_symvers {
return %res;
}
+# Each bit represents a restriction of the export and adding a restriction
+# fails the check
+my $type_GPL = 0x1;
+my $type_NOW = 0x2;
+my $type_UNUSED = 0x4;
+my %types = (
+ EXPORT_SYMBOL => 0x0,
+ EXPORT_SYMBOL_GPL => $type_GPL | $type_NOW,
+ EXPORT_SYMBOL_GPL_FUTURE => $type_GPL,
+ EXPORT_UNUSED_SYMBOL => $type_UNUSED,
+ EXPORT_UNUSED_SYMBOL_GPL => $type_UNUSED | $type_GPL | $type_NOW
+);
+
+sub type_compatible {
+ my ($old, $new) = @_;
+
+ for my $type ($old, $new) {
+ if (!exists($types{$type})) {
+ print STDERR "error: unrecognized export type $type.\n";
+ exit 1;
+ }
+ }
+ # if $new has a bit set that $old does not -> fail
+ return !(~$types{$old} & $types{$new});
+}
+
my $kabi_errors = 0;
sub kabi_change {
- my ($sym, $mod, $oldcrc, $newcrc) = @_;
+ my ($sym, $mod, $message) = @_;
my $fail = 1;
for my $rule (@rules) {
@@ -84,12 +110,7 @@ sub kabi_change {
}
}
return unless $fail or $opt_verbose;
- print STDERR "KABI: symbol $sym($mod) ";
- if ($newcrc) {
- print STDERR "changed crc from $oldcrc to $newcrc"
- } else {
- print STDERR "lost";
- }
+ print STDERR "KABI: symbol $sym($mod) $message";
if ($fail) {
$kabi_errors++;
print STDERR "\n";
@@ -118,10 +139,13 @@ my %new = load_symvers($ARGV[1]);
for my $sym (sort keys(%old)) {
if (!$new{$sym}) {
- kabi_change($sym, $old{$sym}->{mod}, $old{$sym}->{crc}, 0);
+ kabi_change($sym, $old{$sym}->{mod}, "lost");
} elsif ($old{$sym}->{crc} ne $new{$sym}->{crc}) {
- kabi_change($sym, $new{$sym}->{mod}, $old{$sym}->{crc},
- $new{$sym}->{crc});
+ kabi_change($sym, $old{$sym}->{mod}, "changed crc from " .
+ "$old{$sym}->{crc} to $new{$sym}->{crc}");
+ } elsif (!type_compatible($old{$sym}->{type}, $new{$sym}->{type})) {
+ kabi_change($sym, $old{$sym}->{mod}, "changed type from " .
+ "$old{$sym}->{type} to $new{$sym}->{type}");
}
}
if ($kabi_errors) {
diff --git a/rpm/kernel-binary.spec.in b/rpm/kernel-binary.spec.in
index 6546e88669..bcd798680d 100644
--- a/rpm/kernel-binary.spec.in
+++ b/rpm/kernel-binary.spec.in
@@ -81,7 +81,7 @@ BuildRequires: libelf-devel
Provides: %name = %version-%source_rel
# bnc#901925
Provides: %name-%version-%source_rel
-Provides: %{name}_%_target_cpu = %version-%release
+Provides: %{name}_%_target_cpu = %version-%source_rel
Provides: kernel-base = %version-%source_rel
Provides: multiversion(kernel)
# In SLE11, kernel-$flavor complemented kernel-$flavor-base. With SLE12,
@@ -91,6 +91,7 @@ Provides: multiversion(kernel)
# owned by multiple packages now. The dependency is not correct wrt openSUSE
# 11.2 - 11.4, but we primarily care about the supported upgrade path.
Obsoletes: %name-base < 3.1
+Recommends: kernel-firmware
# The following is copied to the -base subpackage as well
# BEGIN COMMON DEPS
Requires(pre): coreutils awk
@@ -153,7 +154,10 @@ Conflicts: hyper-v < 4
Conflicts: libc.so.6()(64bit)
%endif
Provides: kernel = %version-%source_rel
+Provides: kernel-%build_flavor-base-srchash = @COMMIT_FULL@
+Provides: kernel-srchash = @COMMIT_FULL@
# END COMMON DEPS
+Provides: %name-srchash = @COMMIT_FULL@
@PROVIDES_OBSOLETES@
@PROVIDES_OBSOLETES_BASE@
%obsolete_rebuilds %name
@@ -280,7 +284,13 @@ awk '
print $(NF);
}
' >%kernel_build_dir/Module.supported
-for package in base @KMPS@; do
+subpackages=(
+ base
+%if %CONFIG_SUSE_KERNEL_SUPPORTED == "y"
+ @KMPS@
+%endif
+)
+for package in "${subpackages[@]}"; do
%_sourcedir/guards --default=0 "$package" \
<%_sourcedir/supported.conf | sed 's,.*/,,; s,\.ko$,,' | \
sort -u >%kernel_build_dir/Module."$package"
@@ -331,9 +341,18 @@ if test -e %my_builddir/config.addon/%cpu_arch_flavor; then
# the top of the specfile
../scripts/kconfig/merge_config.sh -m .config %my_builddir/config.addon/%cpu_arch_flavor
fi
+
+CONFIG_SUSE_KERNEL_RELEASED="--disable CONFIG_SUSE_KERNEL_RELEASED"
+%if 0%{?_project:1}
+if echo %_project | egrep -qx -f %_sourcedir/release-projects; then
+ CONFIG_SUSE_KERNEL_RELEASED="--enable CONFIG_SUSE_KERNEL_RELEASED"
+fi
+%endif
+
../scripts/config \
--set-str CONFIG_LOCALVERSION -%source_rel-%build_flavor \
--enable CONFIG_SUSE_KERNEL \
+ $CONFIG_SUSE_KERNEL_RELEASED \
%if 0%{?__debug_package:1}
--enable CONFIG_DEBUG_INFO
%else
@@ -420,9 +439,12 @@ done
%install
# sign the modules, firmware and possibly the kernel in the buildservice
-export BRP_PESIGN_FILES="*.ko"
+BRP_PESIGN_FILES=""
%if %CONFIG_EFI_STUB == "y"
-BRP_PESIGN_FILES="$BRP_PESIGN_FILES /boot/vmlinuz-%kernelrelease-%build_flavor"
+BRP_PESIGN_FILES="/boot/vmlinuz-%kernelrelease-%build_flavor"
+%endif
+%if %CONFIG_MODULE_SIG == "y"
+BRP_PESIGN_FILES="$BRP_PESIGN_FILES *.ko"
%endif
%ifarch %ix86
# XXX: do not sign on x86, as the repackaging changes kernel-pae
@@ -442,6 +464,7 @@ export STRIP_KEEP_SYMTAB='*/vmlinux-*'
export NO_BRP_STALE_LINK_ERROR=yes
cd %kernel_build_dir
+source .kernel-binary.spec.buildenv
mkdir -p %buildroot/boot
# (Could strip out non-public symbols.)
@@ -702,12 +725,21 @@ if [ %CONFIG_MODULES = y ]; then
fi
fi
- # arch/powerpc/lib/crtsavres.o is required for building external
- # modules on powerpc
- if [ -f %kernel_build_dir/arch/powerpc/lib/crtsavres.o ]; then
- echo arch/powerpc/lib/crtsavres.o >> %my_builddir/obj-files
+ # Check the license in each module
+ if ! sh %_sourcedir/check-module-license %buildroot; then
+ echo "Please fix the missing licenses!"
+%if %CONFIG_SUSE_KERNEL_SUPPORTED == "y"
+ exit 1
+%endif
fi
+ # These files are required for building external modules
+ for FILE in arch/powerpc/lib/crtsavres.o arch/arm64/kernel/ftrace-mod.o; do
+ if [ -f %kernel_build_dir/$FILE ]; then
+ echo $FILE >> %my_builddir/obj-files
+ fi
+ done
+
tar -cf - -T %my_builddir/obj-files | \
tar -xf - -C %rpm_install_dir/%cpu_arch_flavor
# bnc#507084
@@ -837,7 +869,7 @@ Group: System/Kernel
Url: http://www.kernel.org/
Provides: kernel-base = %version-%source_rel
Provides: multiversion(kernel)
-Conflicts: %name = %version-%release
+Conflicts: %name = %version-%source_rel
@COMMON_DEPS@
@PROVIDES_OBSOLETES_BASE@
%obsolete_rebuilds %name-base
@@ -868,10 +900,10 @@ This package contains only the base modules, required in all installs.
Summary: @SUMMARY@ - Unsupported kernel modules
Group: System/Kernel
Url: http://www.kernel.org/
-Provides: %name-extra_%_target_cpu = %version-%release
+Provides: %name-extra_%_target_cpu = %version-%source_rel
Provides: kernel-extra = %version-%source_rel
Provides: multiversion(kernel)
-Requires: %{name}_%_target_cpu = %version-%release
+Requires: %{name}_%_target_cpu = %version-%source_rel
Requires(pre): coreutils awk
Requires(post): modutils
Requires(post): perl-Bootloader
@@ -985,16 +1017,18 @@ static, unlike the kgraft-patch-<kernel-version>-flavor package names.
%dir /lib/modules/%kernelrelease-%build_flavor
%endif
+%if %CONFIG_SUSE_KERNEL_SUPPORTED == "y"
# BEGIN KMP
%package -n @KMP_NAME@-%build_flavor
Summary: @KMP_SUMMARY@
Group: System/Kernel
-Requires: %name = %version-%release
-Provides: @KMP_NAME@ = %version-%release
+Requires: %name = %version-%source_rel
+Provides: @KMP_NAME@ = %version-%source_rel
Provides: multiversion(kernel)
# tell weak-modules2 to ignore this package
Provides: kmp_in_kernel
Requires(post): suse-module-tools >= 12.4
+@KMP_DEPS@
%description -n @KMP_NAME@-%build_flavor
@KMP_DESCRIPTION@
@@ -1026,6 +1060,7 @@ rm -f "/var/run/rpm-$nvr-modules"
%files -n @KMP_NAME@-%build_flavor -f @KMP_NAME@.files
%defattr(-, root, root)
# END KMP
+%endif # %CONFIG_SUSE_KERNEL_SUPPORTED
%endif # %CONFIG_MODULES
%changelog
diff --git a/rpm/kernel-module-subpackage b/rpm/kernel-module-subpackage
index 9be379add2..e195f0f8d2 100644
--- a/rpm/kernel-module-subpackage
+++ b/rpm/kernel-module-subpackage
@@ -26,6 +26,7 @@ Provides: multiversion(kernel)
Requires: coreutils grep
%{-c:Requires: %{-n*}-ueficert}
Enhances: kernel-%1
+Supplements: packageand(kernel-%1:%{-n*})
%if "%1" == "default"
Obsoletes: %{-n*}-kmp-trace
%ifarch %ix86
diff --git a/rpm/kernel-obs-build.spec.in b/rpm/kernel-obs-build.spec.in
index 768f8119f2..a93c0a6406 100644
--- a/rpm/kernel-obs-build.spec.in
+++ b/rpm/kernel-obs-build.spec.in
@@ -21,6 +21,7 @@
%define patchversion @PATCHVERSION@
%define variant @VARIANT@%{nil}
+%define vanilla_only @VANILLA_ONLY@
%include %_sourcedir/kernel-spec-macros
@@ -30,9 +31,21 @@ BuildRequires: device-mapper
BuildRequires: util-linux
%if 0%{?suse_version}
-BuildRequires: kernel-default
+%if %vanilla_only
+%define kernel_flavor -vanilla
+%else
+%ifarch %ix86
+%define kernel_flavor -pae
+%else
+%ifarch armv7l armv7hl
+%define kernel_flavor -lpae
+%else
%define kernel_flavor -default
%endif
+%endif
+%endif
+%endif
+BuildRequires: kernel%kernel_flavor-srchash = @COMMIT_FULL@
%if 0%{?rhel_version}
BuildRequires: kernel
@@ -103,7 +116,7 @@ echo "DefaultTasksAccounting=no" >> /etc/systemd/system.conf
# a longer list to have them also available for qemu cross builds where x86_64 kernel runs in eg. arm env.
# this list of modules where available on build workers of build.opensuse.org, so we stay compatible.
-export KERNEL_MODULES="loop dm-mod dm-snapshot binfmt-misc fuse kqemu squashfs ext2 ext3 ext4 reiserfs btrfs nf_conntrack_ipv6 binfmt_misc virtio_pci virtio_mmio virtio_blk virtio_rng fat vfat nls_cp437 nls_iso8859-1 ibmvscsi sd_mod e1000 ibmveth"
+export KERNEL_MODULES="loop dm-mod dm-snapshot binfmt-misc fuse kqemu squashfs ext2 ext3 ext4 reiserfs btrfs xfs nf_conntrack_ipv6 binfmt_misc virtio_pci virtio_mmio virtio_blk virtio_rng fat vfat nls_cp437 nls_iso8859-1 ibmvscsi sd_mod e1000 ibmveth"
# manually load all modules to make sure they're available
for i in $KERNEL_MODULES; do
@@ -133,7 +146,7 @@ ROOT=""
-m "$KERNEL_MODULES" \
-k /boot/%{kernel_name}-*-default -M /boot/System.map-*-default -i /tmp/initrd.kvm -B
%else
-dracut --host-only --drivers="$KERNEL_MODULES" --force /tmp/initrd.kvm `echo /boot/%{kernel_name}-*%{kernel_flavor} | sed -n -e 's,[^-]*-\(.*'%{kernel_flavor}'\),\1,p'`
+dracut --host-only --no-hostonly-cmdline --drivers="$KERNEL_MODULES" --force /tmp/initrd.kvm `echo /boot/%{kernel_name}-*%{kernel_flavor} | sed -n -e 's,[^-]*-\(.*'%{kernel_flavor}'\),\1,p'`
%endif
#cleanup
diff --git a/rpm/kernel-source.spec.in b/rpm/kernel-source.spec.in
index 0d6125fa97..cb145120c7 100644
--- a/rpm/kernel-source.spec.in
+++ b/rpm/kernel-source.spec.in
@@ -43,6 +43,7 @@ BuildRequires: fdupes
BuildRequires: sed
Requires(post): coreutils sed
Provides: %name = %version-%source_rel
+Provides: %name-srchash = @COMMIT_FULL@
Provides: linux
Provides: multiversion(kernel)
Source0: @TARBALL_URL@linux-%srcversion.tar.xz
@@ -93,6 +94,8 @@ Source69: try-disable-staging-driver
Source70: kernel-obs-build.spec.in
Source71: kernel-obs-qa.spec.in
Source72: compress-vmlinux.sh
+Source75: release-projects
+Source76: check-module-license
Source90: SLES-UEFI-SIGN-Certificate-2048.crt
Source100: config.tar.bz2
Source101: config.addon.tar.bz2
diff --git a/rpm/kernel-spec-macros b/rpm/kernel-spec-macros
index 1dab7fbc15..9832601f49 100644
--- a/rpm/kernel-spec-macros
+++ b/rpm/kernel-spec-macros
@@ -6,6 +6,10 @@
%define using_buildservice 0%{?opensuse_bs}
+%if ! 0%{?using_buildservice}
+%define using_buildservice 0%(echo %disturl | grep -q '^obs://build\.[^.]*suse\.' && echo 1)
+%endif
+
# source_rel is the package release string, without the rebuild counter
# generated by the build service. If the release string has a non-digit
# suffix, we keep that suffix and strip the rightmost digit component.
diff --git a/rpm/kernel-syms.spec.in b/rpm/kernel-syms.spec.in
index bf988b947f..12141d66a6 100644
--- a/rpm/kernel-syms.spec.in
+++ b/rpm/kernel-syms.spec.in
@@ -41,6 +41,7 @@ BuildRequires: coreutils
@REQUIRES@
Requires: pesign-obs-integration
Provides: %name = %version-%source_rel
+Provides: %name-srchash = @COMMIT_FULL@
Provides: multiversion(kernel)
Source: README.KSYMS
Requires: kernel-devel%variant = %version-%source_rel
diff --git a/rpm/macros.kernel-source b/rpm/macros.kernel-source
index 62062c4aa3..1e69532597 100644
--- a/rpm/macros.kernel-source
+++ b/rpm/macros.kernel-source
@@ -2,6 +2,42 @@
%kernel_module_package_release 1
%kernel_module_package_buildreqs modutils kernel-syms
+%cpu_arch %(case %_target_cpu in \
+ # from rpm --eval '%ix86' \
+ (i?86 | pentium3 | pentium4 | athlon | geode) \
+ echo "i386" \
+ ;; \
+ (aarch64) \
+ echo "arm64" \
+ ;; \
+ (*)\
+ echo "%_target_cpu" \
+ ;; \
+esac)
+
+%linux_arch %(case %cpu_arch in \
+ (x86_64 | i386) \
+ echo "x86" \
+ ;; \
+ (ppc*) \
+ echo "powerpc" \
+ ;; \
+ (s390x) \
+ echo "s390" \
+ ;; \
+ (arm64) \
+ echo "arm64" \
+ ;; \
+ (armv*) \
+ echo "arm" \
+ ;; \
+ (*) \
+ echo "%cpu_arch" \
+ ;; \
+esac)
+
+%linux_make_arch ARCH=%linux_arch
+
# Defines %flavors_to_build and %kernel_source() as a side effect.
%_kernel_module_package(n:v:r:t:f:Xp:bc:) \
%{expand:%( \
@@ -16,10 +52,10 @@
(*) \
[ -z "%{-X}" -a -n "$flavors" ] && continue ;; \
esac \
- krel=$(make -s -C /usr/src/linux-obj/%_target_cpu/$flavor kernelrelease) \
+ krel=$(make -si -C /usr/src/linux-obj/%_target_cpu/$flavor/ %linux_make_arch kernelrelease 2>/dev/null) \
kver=${krel%%-*} \
flavors_to_build="$flavors_to_build $flavor" \
- echo "%%_suse_kernel_module_subpackage -n %{-n*}%{!-n:%name} -v %{-v*}%{!-v:%version} -r %{-r*}%{!-r:%release} %{-p} %{-b} %{-c:-c} $flavor $kver" \
+ echo "%%_suse_kernel_module_subpackage -n %{-n*}%{!-n:%name} -v %{-v*}%{!-v:%version} -r %{-r*}%{!-r:%release} %{-f} %{-p} %{-b} %{-c:-c} $flavor $kver" \
done \
echo "%%global flavors_to_build${flavors_to_build:-%%nil}" \
echo "%%{expand:%%(test -z '%flavors_to_build' && echo %%%%internal_kmp_error)}" \
@@ -43,9 +79,9 @@
# kernel_module_package: simply pass on all options and arguments.
%kernel_module_package(n:v:r:t:f:xp:bc:) \
- %{expand:%%_kernel_module_package %{-x:-X} %{-n} %{-v} %{-r} %{-t} %{-f} %{-p} %*}
+ %{expand:%%_kernel_module_package %{-x:-X} %{-n} %{-v} %{-r} %{-t} %{-f} %{-p} %{-b} %*}
# suse_kernel_module_package: invert the meaning of the -x flag. (You are not
# supposed to understand why a simple %{-x:}%{!-x:-x} won't work.)
%suse_kernel_module_package(n:v:r:s:f:xp:bc:) \
- %{expand:%%_kernel_module_package %{-x: }%{!-x:-X} %{-n} %{-v} %{-r} %{-s:-t %{-s*}} %{-f} %{-p} %*}
+ %{expand:%%_kernel_module_package %{-x: }%{!-x:-X} %{-n} %{-v} %{-r} %{-s:-t %{-s*}} %{-f} %{-p} %{-b} %*}
diff --git a/rpm/mkspec b/rpm/mkspec
index a6020a4155..e0b905e741 100755
--- a/rpm/mkspec
+++ b/rpm/mkspec
@@ -20,6 +20,14 @@ my %flavor_archs = parse_config_conf();
# subset to include in kernel-syms
my %syms_flavor_archs = parse_config_conf("syms");
+my %all_archs = parse_config_conf("needs_updating");
+my @all_archs;
+ for my $flavor (keys(%all_archs)) {
+ push(@all_archs, arch2rpm(@{$all_archs{$flavor}}));
+ }
+@all_archs = sort(uniq(@all_archs));
+my $all_archs = join(" ", @all_archs);
+
# template name -> template body
my %templates = read_spec_templates();
@@ -34,7 +42,7 @@ if (!defined ($rpmrelease)) {
$rpmrelease = $vars{'RELEASE'} || 0;
}
-# package name -> [summary, description]
+# package name -> [summary, description, extra kmp deps]
my %binary_descriptions = parse_descriptions();
# arch -> flavor -> [obsoleted packages]
@@ -75,6 +83,7 @@ if ($srcversion =~ /^(\d+)(?:\.\d+)*(-rc\d+)?$/) {
}
my $commit = get_commit();
+my $commit_full = get_commit(1);
my %macros = (
VARIANT => $variant,
@@ -85,6 +94,7 @@ my %macros = (
TARBALL_URL => $tarball_url,
RELEASE => $rpmrelease,
COMMIT => $commit,
+ COMMIT_FULL => $commit_full,
SOURCES => $sources,
NOSOURCE => $nosource,
UNPACK_PATCHES => $unpack_patches,
@@ -96,20 +106,23 @@ my %macros = (
my $kmp_definitions = "";
my @kmp_definitions;
for my $kmp (@kmps) {
- my ($summary, $description);
+ my ($summary, $description, $deps);
if (!exists($binary_descriptions{$kmp})) {
print STDERR "warning: no description for $kmp found\n";
($summary = $kmp) =~ s/-kmp$//;
$summary .= " kernel modules";
$description = "$summary.";
+ $deps = "";
} else {
$summary = $binary_descriptions{$kmp}->[0];
$description = $binary_descriptions{$kmp}->[1];
+ $deps = $binary_descriptions{$kmp}->[2];
}
push(@kmp_definitions, expand_template("kmp",
KMP_NAME => $kmp,
KMP_SUMMARY => $summary,
- KMP_DESCRIPTION => $description));
+ KMP_DESCRIPTION => $description,
+ KMP_DEPS => $deps));
}
$kmp_definitions = join("\n", @kmp_definitions);
@@ -152,43 +165,49 @@ do_spec('source', "kernel-source$variant.spec", %macros,
ARCHS => join(" ", sort(keys %source_archs))
);
-# kernel-docs.spec
-do_spec('docs', "kernel-docs$variant.spec", %macros);
+if ($variant eq "") {
+ # kernel-docs.spec
+ do_spec('docs', "kernel-docs$variant.spec", %macros);
+}
# kernel-syms.spec
{
my $requires = "";
- my %all_archs;
- my $all_archs;
+ my %syms_archs;
+ my $syms_archs;
for my $flavor (sort keys(%syms_flavor_archs)) {
next if $flavor eq "vanilla";
my @archs = arch2rpm(@{$syms_flavor_archs{$flavor}});
- $all_archs{$_} = 1 for @archs;
+ $syms_archs{$_} = 1 for @archs;
$requires .= "%ifarch @archs\n";
$requires .= "Requires: kernel-$flavor-devel = \%version-\%source_rel\n";
$requires .= "%endif\n";
}
chomp $requires;
- $all_archs = join(" ", sort(keys(%all_archs)));
- if (keys(%all_archs)) {
+ $syms_archs = join(" ", sort(keys(%syms_archs)));
+ if (keys(%syms_archs)) {
do_spec('syms', "kernel-syms$variant.spec", %macros,
REQUIRES => $requires,
- ARCHS => $all_archs);
+ ARCHS => $syms_archs);
}
}
# kernel-obs-*.spec
-{
- my @default_archs = arch2rpm(@{$flavor_archs{default}});
+if (!$variant) {
+ my @default_archs;
+
+ if ($vanilla_only) {
+ @default_archs = arch2rpm(@{$flavor_archs{vanilla}});
+ } else {
+ @default_archs = arch2rpm(@{$flavor_archs{default}});
+ }
# No kernel-obs-* for 32bit ppc
@default_archs = grep { $_ ne "ppc" } @default_archs;
my $default_archs = join(" ", @default_archs);
- if (!$variant) {
- do_spec('obs-build', "kernel-obs-build.spec", %macros,
- ARCHS => $default_archs);
- do_spec('obs-qa', "kernel-obs-qa.spec", %macros,
- ARCHS => $default_archs);
- }
+ do_spec('obs-build', "kernel-obs-build.spec", %macros,
+ ARCHS => $default_archs);
+ do_spec('obs-qa', "kernel-obs-qa.spec", %macros,
+ ARCHS => $default_archs);
}
copy_changes();
@@ -290,13 +309,15 @@ sub parse_descriptions {
if ($current) {
chomp $current->[1];
}
- $current = ["", ""];
+ $current = ["", "", ""];
$res{$package} = $current;
$state = 0;
next;
}
if (/^$/) {
- if ($state == 2) {
+ if ($state == 0) {
+ $state++;
+ } elsif ($state == 2) {
$blank .= $_;
}
next;
@@ -304,12 +325,27 @@ sub parse_descriptions {
# non-blank line and not === package ===
if ($state == 0) {
chomp;
- $current->[0] = $_;
- $state = 1;
+ if (s/^Requires: *//) {
+ # foo-kmp is a shorthand for another kmp
+ # from the same specfile
+ s/-kmp/-kmp-%build_flavor = %version-%release/g;
+ s/^/Requires: /;
+ if ($current->[2]) {
+ $current->[2] .= "\n";
+ }
+ $current->[2] .= $_;
+ } else {
+ # The Summary: keyword is optional
+ s/^Summary: *//;
+ if ($current->[0]) {
+ print STDERR "warning: multi-line summary\n";
+ }
+ $current->[0] = $_;
+ }
} elsif ($state == 1) {
$current->[1] = $_;
$blank = "";
- $state = 2;
+ $state++;
} else {
$current->[1] .= $blank;
$blank = "";
@@ -425,7 +461,9 @@ sub provides_obsoletes {
}
sub get_commit {
- my ($commit, $fh);
+ my ($commit, $fh, $full);
+
+ $full = $_[0] // 0;
if (!open($fh, '<', "source-timestamp")) {
print STDERR "warning: source-timestamp: $!\n";
@@ -433,7 +471,7 @@ sub get_commit {
return "0000000";
}
while (<$fh>) {
- if (/^GIT Revision: ([0-9a-f]{7})/) {
+ if ($full ? /^GIT Revision: ([0-9a-f]{40})/ : /^GIT Revision: ([0-9a-f]{7})/) {
$commit = $1;
}
}
@@ -494,3 +532,7 @@ sub xopen {
open($_[0], $_[1], $_[2]) or die "$_[2]: $!\n";
}
+sub uniq {
+ my %seen;
+ return grep { !$seen{$_}++ } @_;
+}
diff --git a/rpm/package-descriptions b/rpm/package-descriptions
index 6753f6083d..bde83aa467 100644
--- a/rpm/package-descriptions
+++ b/rpm/package-descriptions
@@ -1,13 +1,15 @@
# Descriptions of the binary kernel packages. The format is
#
# === <package name> ===
-# Summary (single line)
+# Summary: Package summary (single line)
+# Requires: additional dependencies for KMPs (single line)
+# ...
#
# Long description (multiple
# lines)
#
# Descriptions of the -base and -extra subpackages are derived from the
-# main descriptions.
+# main descriptions. The "Summary:" keyword can be omitted
=== kernel-debug ===
A Debug Version of the Kernel
@@ -20,6 +22,18 @@ The Standard Kernel
The standard kernel for both uniprocessor and multiprocessor systems.
+=== kernel-kvmsmall ===
+The Small Developer Kernel for KVM
+
+This kernel is intended for kernel developers to use in simple virtual
+machines. It contains only the device drivers necessary to use a
+KVM virtual machine *without* device passthrough enabled. Common
+local and network file systems are enabled. All device mapper targets
+are enabled. Only the network and graphics drivers for devices that qemu
+emulates are enabled. Many subsystems enabled in the default kernel
+are entirely disabled. This kernel is meant to be small and to build
+very quickly. The configuration may change arbitrarily between builds.
+
=== Kernel-azure ===
Kernel for use in the MS Azure cloud and other Hyper-V based virtualization
solutions.
@@ -103,7 +117,8 @@ This kernel should only be used by the s390-tools package. This kernel
should not be installed as a regular booting kernel.
=== cluster-md-kmp ===
-Clustering support for MD devices
+Summary: Clustering support for MD devices
+Requires: dlm-kmp
Clustering support for MD devices. This enables locking and
synchronization across multiple systems on the cluster, so all
@@ -116,12 +131,14 @@ DLM stands for Distributed Lock Manager, a means to synchronize access to
shared resources over the cluster.
=== gfs2-kmp ===
-GFS2 kernel modules
+Summary: GFS2 kernel modules
+Requires: dlm-kmp
GFS2 is Global Filesystem, a shared device filesystem.
=== ocfs2-kmp ===
-OCFS2 kernel modules
+Summary: OCFS2 kernel modules
+Requires: dlm-kmp
OCFS2 is the Oracle Cluster Filesystem, a filesystem for shared devices
accessible simultaneously from multiple nodes of a cluster.
@@ -146,3 +163,9 @@ reproduced, verified and corrected.
Selftest drivers are intended to be supported only in testing and QA
environments, they are not intended to be run on production systems.
+
+=== reiserfs-kmp ===
+Reiserfs kernel module
+
+The reiserfs file system is no longer supported in SLE15. This package
+provides the reiserfs module for the installation system.
diff --git a/rpm/release-projects b/rpm/release-projects
new file mode 100644
index 0000000000..7c7eae20f4
--- /dev/null
+++ b/rpm/release-projects
@@ -0,0 +1,18 @@
+# This file contains regular expressions that define which projects
+# are considered part of an official release channel.
+# This will mark the kernel as released when it's built.
+SUSE:SLE-.*
+openSUSE:[0-9].*:Update
+openSUSE:[0-9].*:Update:Test
+openSUSE:[0-9].*
+openSUSE:Leap
+openSUSE:Leap:.*
+openSUSE:Maintenance
+openSUSE:Maintenance:.*
+openSUSE:Evergreen:Maintenance
+openSUSE:Evergreen:Maintenance:.*
+openSUSE:Tumbleweed
+openSUSE:Tumbleweed:.*
+openSUSE:Factory
+openSUSE:Factory:.*
+PTF:.*
diff --git a/rpm/split-modules b/rpm/split-modules
index 493d698925..ecb967e921 100755
--- a/rpm/split-modules
+++ b/rpm/split-modules
@@ -106,7 +106,7 @@ endif
add_dependent_modules()
{
- xargs -r make EXPLAIN=$1 -rRs -C "$tmp/empty" -f "$tmp/dep" | sort -u
+ xargs -r make $MAKE_ARGS EXPLAIN=$1 -rRs -C "$tmp/empty" -f "$tmp/dep" | sort -u
}
# base
@@ -114,7 +114,7 @@ sed 'y/-/_/' <"$opt_builddir/Module.base" | add_dependent_modules >"$tmp/base"
join -j 1 -o 2.2 "$tmp/base" "$tmp/all" >"$opt_out/base-modules"
# base firmware
-kver=$(make -s -C "$opt_builddir" kernelrelease)
+kver=$(make $MAKE_ARGS -s -C "$opt_builddir" kernelrelease)
if test -d "$opt_dir/lib/firmware/$kver"; then
join <(/sbin/modinfo -F firmware \
$(sed "s:^:$opt_dir:" "$opt_out/base-modules") | sort) \
diff --git a/series.conf b/series.conf
index a2c3dc0363..1509e7ad5f 100644
--- a/series.conf
+++ b/series.conf
@@ -7761,6 +7761,8 @@
patches.fixes/locks-restore-a-warn-for-leaked-locks-on-close.patch
+ patches.fixes/mremap-properly-flush-TLB-before-releasing-the-page.patch
+
########################################################
# IPC patches
########################################################
@@ -8478,7 +8480,6 @@
patches.suse/msft-hv-1533-hyper-v-trace-vmbus_ongpadl_torndown.patch
patches.suse/msft-hv-1534-hyper-v-trace-vmbus_onversion_response.patch
patches.suse/msft-hv-1544-scsi-storvsc-Avoid-excessive-host-scan-on-controller.patch
- patches.suse/msft-hv-1545-PCI-hv-Use-effective-affinity-mask.patch
patches.suse/msft-hv-1546-hv_netvsc-netvsc_teardown_gpadl-split.patch
patches.suse/msft-hv-1547-hv_netvsc-hide-warnings-about-uninitialized-missing-.patch
patches.suse/msft-hv-1550-hv_netvsc-preserve-hw_features-on-mtu-channels-ringp.patch
@@ -17478,6 +17479,7 @@
patches.drivers/bnxt_re-Make-room-for-mapping-beyond-32-entries.patch
patches.drivers/IB-rxe-don-t-crash-if-allocation-of-crc-algorithm-fa.patch
patches.drivers/IB-mlx5-Fix-RoCE-Address-Path-fields.patch
+ patches.suse/msft-hv-1545-PCI-hv-Use-effective-affinity-mask.patch
patches.drivers/ibmvnic-122-fix-dma_mapping_error-call.patch
patches.drivers/i40e-fix-the-calculation-of-VFs-mac-addresses.patch
patches.drivers/timekeeping-Eliminate-the-stale-declaration-of-ktime.patch
@@ -17649,6 +17651,7 @@
patches.fixes/xfs-do-not-log-recover-swapext-extent-owner-changes-.patch
patches.suse/0014-btrfs-tree-checker-Replace-root-parameter-with-fs_in.patch
patches.suse/0001-btrfs-Validate-child-tree-block-s-level-and-first-ke.patch
+ patches.fixes/cifs-fix-memory-leak-in-SMB2_open-.patch
patches.suse/msft-hv-1610-tools-hv-Fix-IP-reporting-by-KVP-daemon-with-SRIOV.patch
patches.suse/msft-hv-1611-hyper-v-use-GFP_KERNEL-for-hv_context.hv_numa_map.patch
patches.suse/msft-hv-1612-hv-Synthetic-typo-correction.patch
@@ -17712,6 +17715,7 @@
patches.fixes/bpf-properly-enforce-index-mask-to-prevent-out-of-bo.patch
patches.drivers/ibmvnic-Fix-partial-success-login-retries.patch
patches.fixes/0001-cifs-store-the-leaseKey-in-the-fid-on-SMB2_open.patch
+ patches.fixes/CIFS-511c54a2f69195b28afb9dd119f03787b1625bb4-adds-a-check-for-sess.patch
patches.suse/msft-hv-1683-X86-Hyper-V-Enlighten-APIC-access.patch
patches.suse/msft-hv-1684-X86-Hyper-V-Enable-IPI-enlightenments.patch
patches.suse/msft-hv-1685-X86-Hyper-V-Enhanced-IPI-enlightenment.patch
@@ -17719,6 +17723,7 @@
patches.suse/msft-hv-1688-x86-Hyper-V-hv_apic-Include-asm-apic.h.patch
patches.suse/msft-hv-1689-x86-Hyper-V-hv_apic-Build-the-Hyper-V-APIC-condition.patch
patches.suse/msft-hv-1679-Drivers-hv-vmbus-enable-VMBus-protocol-version-5.0.patch
+ patches.suse/rpmsg-Correct-support-for-MODULE_DEVICE_TABLE.patch
patches.suse/msft-hv-1681-Drivers-hv-vmbus-Removed-an-unnecessary-cast-from-vo.patch
patches.fixes/0001-drm-exynos-dsi-mask-frame-done-interrupt.patch
patches.suse/msft-hv-1662-hv_netvsc-propogate-Hyper-V-friendly-name-into-inter.patch
@@ -17774,6 +17779,7 @@
patches.drivers/net-mlx5-Fix-wrong-size-allocation-for-QoS-ETC-TC-re.patch
patches.suse/msft-hv-1713-hv_netvsc-split-sub-channel-setup-into-async-and-syn.patch
patches.arch/bpf-s390-fix-potential-memleak-when-later-bpf_jit_prog-fails
+ patches.fixes/cifs-Fix-use-after-free-of-a-mid_q_entry.patch
patches.fixes/0001-cifs-Fix-stack-out-of-bounds-in-smb-2-3-_create_leas.patch
patches.suse/sched-fair-Fix-bandwidth-timer-clock-drift-condition.patch
patches.suse/msft-hv-1726-x86-hyper-v-Fix-the-circular-dependency-in-IPI-enlig.patch
@@ -17806,6 +17812,7 @@
patches.suse/0017-btrfs-Check-that-each-block-group-has-corresponding-.patch
patches.suse/0018-btrfs-Verify-that-every-chunk-has-corresponding-bloc.patch
patches.suse/0019-btrfs-Introduce-mount-time-chunk-dev-extent-mapping-.patch
+ patches.fixes/smb3-fill-in-statfs-fsid-and-correct-namelen.patch
patches.suse/readahead-stricter-check-for-bdi-io_pages.patch
patches.drivers/be2net-remove-unused-old-custom-busy-poll-fields.patch
patches.drivers/net-mlx5-Add-missing-SET_DRIVER_VERSION-command-tran.patch
@@ -17853,9 +17860,14 @@
patches.drivers/scsi-ipr-System-hung-while-dlpar-adding-primary-ipr-.patch
patches.suse/msft-hv-1760-Drivers-hv-vmbus-Use-get-put_cpu-in-vmbus_connect.patch
patches.suse/msft-hv-1761-tools-hv-fcopy-set-error-in-case-an-unknown-operatio.patch
-
- # davem/net-next
patches.suse/msft-hv-1766-hv_netvsc-fix-vf-serial-matching-with-pci-slot-info.patch
+ patches.suse/hwrng-core-document-the-quality-field.patch
+ patches.fixes/0001-drm-virtio-fix-bounds-check-in-virtio_gpu_cmd_get_ca.patch
+ patches.fixes/0001-drm-hisilicon-hibmc-Do-not-carry-error-code-in-HiBMC.patch
+ patches.fixes/0001-drm-hisilicon-hibmc-Don-t-overwrite-fb-helper-surfac.patch
+ patches.fixes/0001-fbdev-fix-broken-menu-dependencies.patch
+ patches.fixes/0001-memory_hotplug-cond_resched-in-__remove_pages.patch
+ # end of sorted patches
# out-of-tree patches
patches.fixes/xfs-repair-malformed-inode-items-during-log-recovery.patch
@@ -17876,11 +17888,57 @@
patches.kabi/ip-drop-IPSTATS_MIB_REASM_OVERLAPS.patch
patches.kabi/kabi-protect_hnae_ae_ops.patch
- # end of sorted patches
########################################################
# btrfs
########################################################
+ # v4.11
+ patches.suse/btrfs-qgroups-opencode-qgroup_free-helper.patch
+ patches.suse/0001-Btrfs-pass-delayed_refs-directly-to-btrfs_find_delay.patch
+ patches.suse/0002-Btrfs-kill-trans-in-run_delalloc_nocow-and-btrfs_cro.patch
+ # v4.12
+ patches.suse/0001-btrfs-qgroup-Add-trace-point-for-qgroup-reserved-spa.patch
+ patches.suse/0001-Btrfs-fix-invalid-attempt-to-free-reserved-space-on-.patch
+ # v4.14
+ patches.suse/btrfs-add-wrapper-for-counting-BTRFS_MAX_EXTENT_SIZE.patch
+
+ # Upstream qgroup fixes (v4.13~v4.17)
+ patches.suse/0001-btrfs-qgroup-Add-quick-exit-for-non-fs-extents.patch
+ patches.suse/0002-btrfs-qgroup-Cleanup-btrfs_qgroup_prepare_account_ex.patch
+ # 0003~0006 are already merged
+ patches.suse/0007-btrfs-qgroup-Skeleton-to-support-separate-qgroup-res.patch
+ patches.suse/0008-btrfs-qgroup-Introduce-helpers-to-update-and-access-.patch
+ patches.suse/0009-btrfs-qgroup-Make-qgroup_reserve-and-its-callers-to-.patch
+ patches.suse/0010-btrfs-qgroup-Fix-wrong-qgroup-reservation-update-for.patch
+ patches.suse/0011-btrfs-qgroup-Update-trace-events-to-use-new-separate.patch
+ patches.suse/0012-btrfs-qgroup-Cleanup-the-remaining-old-reservation-c.patch
+ patches.suse/0013-btrfs-qgroup-Split-meta-rsv-type-into-meta_prealloc-.patch
+ patches.suse/0014-btrfs-qgroup-Don-t-use-root-qgroup_meta_rsv-for-qgro.patch
+ patches.suse/0015-btrfs-qgroup-Introduce-function-to-convert-META_PREA.patch
+ patches.suse/0016-btrfs-cleanup-extent-locking-sequence.patch
+ patches.suse/0017-Btrfs-rework-outstanding_extents.patch
+ patches.suse/0018-btrfs-add-tracepoints-for-outstanding-extents-mods.patch
+ patches.suse/0019-btrfs-make-the-delalloc-block-rsv-per-inode.patch
+ patches.suse/0020-btrfs-remove-type-argument-from-comp_tree_refs.patch
+ patches.suse/0021-btrfs-switch-args-for-comp_-_refs.patch
+ patches.suse/0022-btrfs-add-a-comp_refs-helper.patch
+ patches.suse/0023-btrfs-qgroup-Use-separate-meta-reservation-type-for-.patch
+ patches.suse/0024-btrfs-Fix-wrong-btrfs_delalloc_release_extents-param.patch
+ patches.suse/0025-btrfs-delayed-inode-Use-new-qgroup-meta-rsv-for-dela.patch
+ patches.suse/0026-btrfs-qgroup-Use-root-qgroup_meta_rsv_-to-record-qgr.patch
+ patches.suse/0027-btrfs-qgroup-Update-trace-events-for-metadata-reserv.patch
+ patches.suse/0028-Revert-btrfs-qgroups-Retry-after-commit-on-getting-E.patch
+ patches.suse/0029-btrfs-qgroup-Commit-transaction-in-advance-to-reduce.patch
+ patches.suse/0030-btrfs-qgroup-Use-independent-and-accurate-per-inode-.patch
+ patches.suse/0031-btrfs-delayed-inode-Remove-wrong-qgroup-meta-reserva.patch
+
+ # v4.17
+ patches.fixes/0001-btrfs-Take-trans-lock-before-access-running-trans-in.patch
+ # v4.20 or v5.0
+ patches.fixes/0001-btrfs-Enhance-btrfs_trim_fs-function-to-handle-error.patch
+ patches.fixes/0002-btrfs-Ensure-btrfs_trim_fs-can-trim-the-whole-filesy.patch
+ patches.fixes/0001-btrfs-defrag-use-btrfs_mod_outstanding_extents-in-cl.patch
+
# Not upstream yet
patches.suse/btrfs-8059-syslog-when-quota-is-enabled.patch
patches.suse/btrfs-8060-syslog-when-quota-is-disabled.patch
@@ -19139,6 +19197,7 @@
patches.suse/suse-hv-guest-os-id.patch
patches.suse/suse-hv-kvp_on_msg.dbg.patch
patches.suse/suse-hv-vmbus-sysfs-ring_buffer.patch
+ patches.suse/irq_data_get_effective_affinity_mask.patch
patches.drivers/watchdog-hpwdt-HP-rebranding.patch
patches.fixes/watchdog-hpwdt-add-support-for-iLO5.patch
@@ -19285,6 +19344,8 @@
patches.drivers/watchdog-w83627hf_wdt-support-NCT6102.patch
patches.drivers/watchdog-w83627hf_wdt-support-Inves.patch
+ patches.fixes/cdrom-fix-improper-type-cast-which-can-leat-to-infor.patch
+
########################################################
# Other drivers we have added to the tree
########################################################
@@ -22406,6 +22467,8 @@
patches.fixes/cgroup-remove-redundant-cleanup-in-css_create.patch
patches.fixes/cgroup-net_cls-iterate-the-fds-of-only-the-tasks-whi.patch
+ patches.fixes/0001-cgroup-netclassid-add-a-preemption-point-to-write_cl.patch
+
# Fix for bnc#972552
########################################################
@@ -23006,6 +23069,7 @@
patches.drivers/tpm-125-vtpm_proxy-conditionally-call-tpm_chip_unregiste.patch
patches.drivers/tpm-126-adjust-return-value-of-tpm_read_log.patch
patches.drivers/tpm-127-use-idr_find-not-idr_find_slowpath.patch
+ patches.drivers/tpm-Restore-functionality-to-xen-vtpm-driver.patch
# Qualcomm TPM fate#320512, v4.11rc2 update
patches.drivers/tpm-128-add-kdoc-for-tpm_transmit-and-tpm_transmit_cmd.patch
@@ -25561,6 +25625,11 @@
patches.drivers/0001-mmc-mmci-stop-building-qcom-dml-as-module.patch
patches.drivers/0002-phy-qcom-ufs-add-MODULE_LICENSE-tag.patch
+ # bsc#1114648
+ patches.fixes/x86-kexec-correct-kexec_backup_src_end-off-by-one-error.patch
+ patches.fixes/resource-include-resource-end-in-walk_-interfaces.patch
+ patches.fixes/edac-thunderx-fix-memory-leak-in-thunderx_l2c_threaded_isr.patch
+
########################################################
# kGraft
########################################################